Drizzled Public API Documentation

join_table.cc
00001 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008-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 <drizzled/field/blob.h>
00024 #include <drizzled/join_table.h>
00025 #include <drizzled/sql_lex.h>
00026 #include <drizzled/sql_select.h>
00027 #include <drizzled/table.h>
00028 #include <drizzled/util/test.h>
00029 
00030 namespace drizzled
00031 {
00032 
00033 int JoinTable::joinReadConstTable(optimizer::Position *pos)
00034 {
00035   int error;
00036   Table *Table= this->table;
00037   Table->const_table=1;
00038   Table->null_row=0;
00039   Table->status=STATUS_NO_RECORD;
00040 
00041   if (this->type == AM_SYSTEM)
00042   {
00043     if ((error=this->joinReadSystem()))
00044     {           // Info for DESCRIBE
00045       this->info="const row not found";
00046       /* Mark for EXPLAIN that the row was not found */
00047       pos->setFanout(0.0);
00048       pos->clearRefDependMap();
00049       if (! Table->maybe_null || error > 0)
00050         return(error);
00051     }
00052   }
00053   else
00054   {
00055     if (! Table->key_read && 
00056         Table->covering_keys.test(this->ref.key) && 
00057         ! Table->no_keyread &&
00058         (int) Table->reginfo.lock_type <= (int) TL_READ_WITH_SHARED_LOCKS)
00059     {
00060       Table->key_read=1;
00061       Table->cursor->extra(HA_EXTRA_KEYREAD);
00062       this->index= this->ref.key;
00063     }
00064     error=join_read_const(this);
00065     if (Table->key_read)
00066     {
00067       Table->key_read=0;
00068       Table->cursor->extra(HA_EXTRA_NO_KEYREAD);
00069     }
00070     if (error)
00071     {
00072       this->info="unique row not found";
00073       /* Mark for EXPLAIN that the row was not found */
00074       pos->setFanout(0.0);
00075       pos->clearRefDependMap();
00076       if (!Table->maybe_null || error > 0)
00077         return(error);
00078     }
00079   }
00080   if (*this->on_expr_ref && !Table->null_row)
00081   {
00082     if ((Table->null_row= test((*this->on_expr_ref)->val_int() == 0)))
00083       Table->mark_as_null_row();
00084   }
00085   if (!Table->null_row)
00086     Table->maybe_null=0;
00087 
00088   /* Check appearance of new constant items in Item_equal objects */
00089   Join *Join= this->join;
00090   if (Join->conds)
00091     update_const_equal_items(Join->conds, this);
00092   TableList *tbl;
00093   for (tbl= Join->select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
00094   {
00095     TableList *embedded;
00096     TableList *embedding= tbl;
00097     do
00098     {
00099       embedded= embedding;
00100       if (embedded->on_expr)
00101          update_const_equal_items(embedded->on_expr, this);
00102       embedding= embedded->getEmbedding();
00103     }
00104     while (embedding &&
00105            &embedding->getNestedJoin()->join_list.front() == embedded);
00106   }
00107 
00108   return(0);
00109 }
00110 
00111 void JoinTable::readCachedRecord()
00112 {
00113   unsigned char *pos;
00114   uint32_t length;
00115   bool last_record;
00116   CacheField *copy,*end_field;
00117 
00118   last_record= this->cache.record_nr++ == this->cache.ptr_record;
00119   pos= this->cache.pos;
00120   for (copy= this->cache.field, end_field= copy+this->cache.fields;
00121        copy < end_field;
00122        copy++)
00123   {
00124     if (copy->blob_field)
00125     {
00126       if (last_record)
00127       {
00128         copy->blob_field->set_image(pos, copy->length+sizeof(char*),
00129                   copy->blob_field->charset());
00130         pos+=copy->length+sizeof(char*);
00131       }
00132       else
00133       {
00134         copy->blob_field->set_ptr(pos, pos+copy->length);
00135         pos+=copy->length+copy->blob_field->get_length();
00136       }
00137     }
00138     else
00139     {
00140       if (copy->strip)
00141       {
00142         length= uint2korr(pos);
00143         memcpy(copy->str, pos+2, length);
00144         memset(copy->str+length, ' ', copy->length-length);
00145         pos+= 2 + length;
00146       }
00147       else
00148       {
00149         memcpy(copy->str,pos,copy->length);
00150         pos+=copy->length;
00151       }
00152     }
00153   }
00154   this->cache.pos=pos;
00155 }
00156 
00157 int JoinTable::joinReadSystem()
00158 {
00159   Table *Table= this->table;
00160   int error;
00161   if (Table->status & STATUS_GARBAGE)   // If first read
00162   {
00163     if ((error=Table->cursor->read_first_row(table->getInsertRecord(),
00164              Table->getShare()->getPrimaryKey())))
00165     {
00166       if (error != HA_ERR_END_OF_FILE)
00167         return Table->report_error(error);
00168       this->table->mark_as_null_row();
00169       Table->emptyRecord();     // Make empty record
00170       return -1;
00171     }
00172     Table->storeRecord();
00173   }
00174   else if (!Table->status)      // Only happens with left join
00175     Table->restoreRecord();     // restore old record
00176   Table->null_row=0;
00177   return Table->status ? -1 : 0;
00178 }
00179 
00180 } /* namespace drizzled */