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