Drizzled Public API Documentation

field_iterator.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 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; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #include <config.h>
00021 #include <drizzled/field_iterator.h>
00022 #include <drizzled/table_list.h>
00023 #include <drizzled/session.h>
00024 #include <drizzled/sql_lex.h>
00025 #include <drizzled/table.h>
00026 
00027 namespace drizzled {
00028 
00029 const char *Field_iterator_table::name() const
00030 {
00031   return (*ptr)->field_name;
00032 }
00033 
00034 
00035 void Field_iterator_table::set(TableList *table)
00036 {
00037   ptr= table->table->getFields();
00038 }
00039 
00040 
00041 void Field_iterator_table::set_table(Table *table)
00042 {
00043   ptr= table->getFields();
00044 }
00045 
00046 
00047 Item *Field_iterator_table::create_item(Session *session)
00048 {
00049   return new Item_field(session, &session->lex().current_select->context, *ptr);
00050 }
00051 
00052 
00053 void Field_iterator_natural_join::set(TableList *table_ref)
00054 {
00055   assert(table_ref->join_columns);
00056   column_ref_it= table_ref->join_columns->begin();
00057   cur_column_ref= column_ref_it++;
00058 }
00059 
00060 
00061 void Field_iterator_natural_join::next()
00062 {
00063   cur_column_ref= column_ref_it++;
00064   assert(!cur_column_ref || ! cur_column_ref->table_field ||
00065               cur_column_ref->table_ref->table ==
00066               cur_column_ref->table_field->getTable());
00067 }
00068 
00069 
00070 void Field_iterator_table_ref::set_field_iterator()
00071 {
00072   /*
00073     If the table reference we are iterating over is a natural join, or it is
00074     an operand of a natural join, and TableList::join_columns contains all
00075     the columns of the join operand, then we pick the columns from
00076     TableList::join_columns, instead of the  orginial container of the
00077     columns of the join operator.
00078   */
00079   if (table_ref->is_join_columns_complete)
00080   {
00081     field_it= &natural_join_it;
00082   }
00083   /* This is a base table or stored view. */
00084   else
00085   {
00086     assert(table_ref->table);
00087     field_it= &table_field_it;
00088   }
00089   field_it->set(table_ref);
00090   return;
00091 }
00092 
00093 
00094 void Field_iterator_table_ref::set(TableList *table)
00095 {
00096   assert(table);
00097   first_leaf= table->first_leaf_for_name_resolution();
00098   last_leaf=  table->last_leaf_for_name_resolution();
00099   assert(first_leaf && last_leaf);
00100   table_ref= first_leaf;
00101   set_field_iterator();
00102 }
00103 
00104 
00105 void Field_iterator_table_ref::next()
00106 {
00107   /* Move to the next field in the current table reference. */
00108   field_it->next();
00109   /*
00110     If all fields of the current table reference are exhausted, move to
00111     the next leaf table reference.
00112   */
00113   if (field_it->end_of_fields() && table_ref != last_leaf)
00114   {
00115     table_ref= table_ref->next_name_resolution_table;
00116     assert(table_ref);
00117     set_field_iterator();
00118   }
00119 }
00120 
00121 
00122 const char *Field_iterator_table_ref::table_name()
00123 {
00124   if (table_ref->is_natural_join)
00125     return natural_join_it.column_ref()->table_name();
00126 
00127   assert(!strcmp(table_ref->getTableName(),
00128                  table_ref->table->getShare()->getTableName()));
00129   return table_ref->getTableName();
00130 }
00131 
00132 
00133 const char *Field_iterator_table_ref::db_name()
00134 {
00135   if (table_ref->is_natural_join)
00136     return natural_join_it.column_ref()->db_name();
00137 
00138   /*
00139     Test that TableList::db is the same as TableShare::db to
00140     ensure consistency. 
00141   */
00142   assert(!strcmp(table_ref->getSchemaName(), table_ref->table->getShare()->getSchemaName()));
00143   return table_ref->getSchemaName();
00144 }
00145 
00146 
00147 
00148 /*
00149   Create new or return existing column reference to a column of a
00150   natural/using join.
00151 
00152   SYNOPSIS
00153     Field_iterator_table_ref::get_or_create_column_ref()
00154     parent_table_ref  the parent table reference over which the
00155                       iterator is iterating
00156 
00157   DESCRIPTION
00158     Create a new natural join column for the current field of the
00159     iterator if no such column was created, or return an already
00160     created natural join column. The former happens for base tables or
00161     views, and the latter for natural/using joins. If a new field is
00162     created, then the field is added to 'parent_table_ref' if it is
00163     given, or to the original table referene of the field if
00164     parent_table_ref == NULL.
00165 
00166   NOTES
00167     This method is designed so that when a Field_iterator_table_ref
00168     walks through the fields of a table reference, all its fields
00169     are created and stored as follows:
00170     - If the table reference being iterated is a stored table, view or
00171       natural/using join, store all natural join columns in a list
00172       attached to that table reference.
00173     - If the table reference being iterated is a nested join that is
00174       not natural/using join, then do not materialize its result
00175       fields. This is OK because for such table references
00176       Field_iterator_table_ref iterates over the fields of the nested
00177       table references (recursively). In this way we avoid the storage
00178       of unnecessay copies of result columns of nested joins.
00179 
00180   RETURN
00181     #     Pointer to a column of a natural join (or its operand)
00182     NULL  No memory to allocate the column
00183 */
00184 
00185 Natural_join_column *
00186 Field_iterator_table_ref::get_or_create_column_ref(TableList *parent_table_ref)
00187 {
00188   Natural_join_column *nj_col;
00189   bool is_created= true;
00190   uint32_t field_count=0;
00191   TableList *add_table_ref= parent_table_ref ?
00192                              parent_table_ref : table_ref;
00193 
00194   if (field_it == &table_field_it)
00195   {
00196     /* The field belongs to a stored table. */
00197     Field *tmp_field= table_field_it.field();
00198     nj_col= new Natural_join_column(tmp_field, table_ref);
00199     field_count= table_ref->table->getShare()->sizeFields();
00200   }
00201   else
00202   {
00203     /*
00204       The field belongs to a NATURAL join, therefore the column reference was
00205       already created via one of the two constructor calls above. In this case
00206       we just return the already created column reference.
00207     */
00208     assert(table_ref->is_join_columns_complete);
00209     is_created= false;
00210     nj_col= natural_join_it.column_ref();
00211     assert(nj_col);
00212   }
00213   assert(!nj_col->table_field ||
00214               nj_col->table_ref->table == nj_col->table_field->getTable());
00215 
00216   /*
00217     If the natural join column was just created add it to the list of
00218     natural join columns of either 'parent_table_ref' or to the table
00219     reference that directly contains the original field.
00220   */
00221   if (is_created)
00222   {
00223     /* Make sure not all columns were materialized. */
00224     assert(!add_table_ref->is_join_columns_complete);
00225     if (!add_table_ref->join_columns)
00226     {
00227       /* Create a list of natural join columns on demand. */
00228       add_table_ref->join_columns= new List<Natural_join_column>;
00229       add_table_ref->is_join_columns_complete= false;
00230     }
00231     add_table_ref->join_columns->push_back(nj_col);
00232     /*
00233       If new fields are added to their original table reference, mark if
00234       all fields were added. We do it here as the caller has no easy way
00235       of knowing when to do it.
00236       If the fields are being added to parent_table_ref, then the caller
00237       must take care to mark when all fields are created/added.
00238     */
00239     if (!parent_table_ref &&
00240         add_table_ref->join_columns->size() == field_count)
00241       add_table_ref->is_join_columns_complete= true;
00242   }
00243 
00244   return nj_col;
00245 }
00246 
00247 
00248 /*
00249   Return an existing reference to a column of a natural/using join.
00250 
00251   SYNOPSIS
00252     Field_iterator_table_ref::get_natural_column_ref()
00253 
00254   DESCRIPTION
00255     The method should be called in contexts where it is expected that
00256     all natural join columns are already created, and that the column
00257     being retrieved is a Natural_join_column.
00258 
00259   RETURN
00260     #     Pointer to a column of a natural join (or its operand)
00261     NULL  No memory to allocate the column
00262 */
00263 
00264 Natural_join_column *
00265 Field_iterator_table_ref::get_natural_column_ref()
00266 {
00267   assert(field_it == &natural_join_it);
00268   /*
00269     The field belongs to a NATURAL join, therefore the column reference was
00270     already created via one of the two constructor calls above. In this case
00271     we just return the already created column reference.
00272   */
00273   Natural_join_column* nj_col= natural_join_it.column_ref();
00274   assert(nj_col && (!nj_col->table_field || nj_col->table_ref->table == nj_col->table_field->getTable()));
00275   return nj_col;
00276 }
00277 
00278 } /* namespace drizzled */