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 #include <drizzled/statistics_variables.h>
00029 
00030 #include <unistd.h>
00031 #include <fcntl.h>
00032 
00033 #include <string>
00034 
00035 using namespace std;
00036 using namespace drizzled;
00037 
00038 /*****************************************************************************
00039 ** Data Function tables
00040 *****************************************************************************/
00041 
00042 FunctionCursor::FunctionCursor(plugin::StorageEngine &engine_arg,
00043                                Table &table_arg) :
00044   Cursor(engine_arg, table_arg),
00045   estimate_of_rows(100), // Completely fabricated, I used to use the value 2.
00046   rows_returned(0)
00047 {}
00048 
00049 int FunctionCursor::open(const char *name, int, uint32_t)
00050 {
00051   tool= static_cast<Function *>(getEngine())->getFunction(name); 
00052 //  assert(tool);
00053 
00054   row_cache_position= 0;
00055 
00056   if (not tool)
00057     return HA_ERR_NO_SUCH_TABLE;
00058 
00059   return 0;
00060 }
00061 
00062 int FunctionCursor::close(void)
00063 {
00064   tool= NULL;
00065   wipeCache();
00066 
00067   return 0;
00068 }
00069 
00070 int FunctionCursor::doStartTableScan(bool)
00071 {
00072   rows_returned= 0;
00073   generator= tool->generator(getTable()->getFields());
00074 
00075   return 0;
00076 }
00077 
00078 
00079 int FunctionCursor::rnd_next(unsigned char *)
00080 {
00081   bool more_rows;
00082   ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
00083 
00084   /* Fix bug in the debug logic for field */
00085   for (Field **field= getTable()->getFields() ; *field ; field++)
00086   {
00087     (*field)->setWriteSet();
00088   }
00089 
00090   more_rows= generator->sub_populate(getTable()->getShare()->sizeFields());
00091 
00092   if (more_rows)
00093   {
00094     return 0;
00095   }
00096   else 
00097   {
00098     delete generator;
00099     generator= NULL;
00100   }
00101   rows_returned++;
00102 
00103   return more_rows ? 0 : HA_ERR_END_OF_FILE;
00104 }
00105 
00106 uint32_t FunctionCursor::max_row_length()
00107 {
00108   uint32_t length= (uint32_t)(getTable()->getRecordLength() + getTable()->sizeFields()*2);
00109 
00110   uint32_t *ptr, *end;
00111   for (ptr= getTable()->getBlobField(), end=ptr + getTable()->sizeBlobFields();
00112        ptr != end ;
00113        ptr++)
00114   {
00115       length += 2 + ((Field_blob*)getTable()->getField(*ptr))->get_length();
00116   }
00117 
00118   return length;
00119 }
00120 
00121 unsigned int FunctionCursor::pack_row(const unsigned char *record)
00122 {
00123   unsigned char *ptr;
00124 
00125   record_buffer.resize(max_row_length());
00126 
00127   /* Copy null bits */
00128   memcpy(&record_buffer[0], record, getTable()->getShare()->null_bytes);
00129   ptr= &record_buffer[0] + getTable()->getShare()->null_bytes;
00130 
00131   for (Field **field=getTable()->getFields() ; *field ; field++)
00132   {
00133     if (!((*field)->is_null()))
00134       ptr= (*field)->pack(ptr, record + (*field)->offset(record));
00135   }
00136 
00137   return((unsigned int) (ptr - &record_buffer[0]));
00138 }
00139 
00140 void FunctionCursor::position(const unsigned char *record)
00141 {
00142   uint32_t max_length= max_row_length();
00143 
00144   if (row_cache.size() <= row_cache_position + max_length)
00145   {
00146     row_cache.resize(row_cache.size() +  max_length);
00147   }
00148 
00149   unsigned int r_pack_length;
00150   r_pack_length= pack_row(record);
00151   internal::my_store_ptr(ref, ref_length, row_cache_position);
00152 
00153   memcpy(&row_cache[row_cache_position], &record_buffer[0], r_pack_length);
00154   row_cache_position+= r_pack_length;
00155 }
00156 
00157 
00158 void FunctionCursor::wipeCache()
00159 {
00160   if (rows_returned > estimate_of_rows)
00161     estimate_of_rows= rows_returned;
00162 
00163   row_cache.clear();
00164   row_cache_position= 0;
00165 }
00166 
00167 int FunctionCursor::extra(enum ha_extra_function operation)
00168 {
00169   switch (operation)
00170   {
00171   case drizzled::HA_EXTRA_CACHE:
00172     break;
00173   case drizzled::HA_EXTRA_NO_CACHE:
00174     break;
00175   case drizzled::HA_EXTRA_RESET_STATE:
00176     wipeCache();
00177     break;
00178   default:
00179     break;
00180   }
00181 
00182   return 0;
00183 }
00184 
00185 int FunctionCursor::doEndTableScan()
00186 { 
00187   delete generator; // Do this in case of an early exit from rnd_next()
00188 
00189   return 0;
00190 }
00191 
00192 int FunctionCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
00193 {
00194   ha_statistic_increment(&system_status_var::ha_read_rnd_count);
00195   size_t position_id= (size_t)internal::my_get_ptr(pos, ref_length);
00196 
00197   const unsigned char *ptr;
00198   ptr= &row_cache[position_id];
00199 
00200   /* Copy null bits */
00201   memcpy(buf, ptr, getTable()->getNullBytes());
00202   ptr+= getTable()->getNullBytes();
00203   // and copy fields
00204   for (Field **field= getTable()->getFields() ; *field ; field++)
00205   {
00206     if (!((*field)->is_null()))
00207     {
00208       ptr= (*field)->unpack(buf + (*field)->offset(getTable()->getInsertRecord()), ptr);
00209     }
00210   }
00211 
00212   return 0;
00213 }
00214 
00215 
00216 int FunctionCursor::info(uint32_t flag)
00217 {
00218   memset(&stats, 0, sizeof(stats));
00219 
00220   if (flag & HA_STATUS_AUTO)
00221     stats.auto_increment_value= 1;
00222 
00223   stats.records= estimate_of_rows;
00224 
00225   return 0;
00226 }