Drizzled Public API Documentation

field_iterator.cc
1 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 Sun Microsystems, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include <config.h>
21 #include <drizzled/field_iterator.h>
22 #include <drizzled/table_list.h>
23 #include <drizzled/session.h>
24 #include <drizzled/sql_lex.h>
25 #include <drizzled/table.h>
26 
27 namespace drizzled {
28 
29 const char *Field_iterator_table::name() const
30 {
31  return (*ptr)->field_name;
32 }
33 
34 
35 void Field_iterator_table::set(TableList *table)
36 {
37  ptr= table->table->getFields();
38 }
39 
40 
41 void Field_iterator_table::set_table(Table *table)
42 {
43  ptr= table->getFields();
44 }
45 
46 
47 Item *Field_iterator_table::create_item(Session *session)
48 {
49  return new Item_field(session, &session->lex().current_select->context, *ptr);
50 }
51 
52 
53 void Field_iterator_natural_join::set(TableList *table_ref)
54 {
55  assert(table_ref->join_columns);
56  column_ref_it= table_ref->join_columns->begin();
57  cur_column_ref= column_ref_it++;
58 }
59 
60 
61 void Field_iterator_natural_join::next()
62 {
63  cur_column_ref= column_ref_it++;
64  assert(!cur_column_ref || ! cur_column_ref->table_field ||
65  cur_column_ref->table_ref->table ==
66  cur_column_ref->table_field->getTable());
67 }
68 
69 
70 void Field_iterator_table_ref::set_field_iterator()
71 {
72  /*
73  If the table reference we are iterating over is a natural join, or it is
74  an operand of a natural join, and TableList::join_columns contains all
75  the columns of the join operand, then we pick the columns from
76  TableList::join_columns, instead of the orginial container of the
77  columns of the join operator.
78  */
79  if (table_ref->is_join_columns_complete)
80  {
81  field_it= &natural_join_it;
82  }
83  /* This is a base table or stored view. */
84  else
85  {
86  assert(table_ref->table);
87  field_it= &table_field_it;
88  }
89  field_it->set(table_ref);
90  return;
91 }
92 
93 
94 void Field_iterator_table_ref::set(TableList *table)
95 {
96  assert(table);
97  first_leaf= table->first_leaf_for_name_resolution();
98  last_leaf= table->last_leaf_for_name_resolution();
99  assert(first_leaf && last_leaf);
100  table_ref= first_leaf;
101  set_field_iterator();
102 }
103 
104 
105 void Field_iterator_table_ref::next()
106 {
107  /* Move to the next field in the current table reference. */
108  field_it->next();
109  /*
110  If all fields of the current table reference are exhausted, move to
111  the next leaf table reference.
112  */
113  if (field_it->end_of_fields() && table_ref != last_leaf)
114  {
115  table_ref= table_ref->next_name_resolution_table;
116  assert(table_ref);
117  set_field_iterator();
118  }
119 }
120 
121 
122 const char *Field_iterator_table_ref::table_name()
123 {
124  if (table_ref->is_natural_join)
125  return natural_join_it.column_ref()->table_name();
126 
127  assert(!strcmp(table_ref->getTableName(),
128  table_ref->table->getShare()->getTableName()));
129  return table_ref->getTableName();
130 }
131 
132 
133 const char *Field_iterator_table_ref::db_name()
134 {
135  if (table_ref->is_natural_join)
136  return natural_join_it.column_ref()->db_name();
137 
138  /*
139  Test that TableList::db is the same as TableShare::db to
140  ensure consistency.
141  */
142  assert(!strcmp(table_ref->getSchemaName(), table_ref->table->getShare()->getSchemaName()));
143  return table_ref->getSchemaName();
144 }
145 
146 
147 
148 /*
149  Create new or return existing column reference to a column of a
150  natural/using join.
151 
152  SYNOPSIS
153  Field_iterator_table_ref::get_or_create_column_ref()
154  parent_table_ref the parent table reference over which the
155  iterator is iterating
156 
157  DESCRIPTION
158  Create a new natural join column for the current field of the
159  iterator if no such column was created, or return an already
160  created natural join column. The former happens for base tables or
161  views, and the latter for natural/using joins. If a new field is
162  created, then the field is added to 'parent_table_ref' if it is
163  given, or to the original table referene of the field if
164  parent_table_ref == NULL.
165 
166  NOTES
167  This method is designed so that when a Field_iterator_table_ref
168  walks through the fields of a table reference, all its fields
169  are created and stored as follows:
170  - If the table reference being iterated is a stored table, view or
171  natural/using join, store all natural join columns in a list
172  attached to that table reference.
173  - If the table reference being iterated is a nested join that is
174  not natural/using join, then do not materialize its result
175  fields. This is OK because for such table references
176  Field_iterator_table_ref iterates over the fields of the nested
177  table references (recursively). In this way we avoid the storage
178  of unnecessay copies of result columns of nested joins.
179 
180  RETURN
181  # Pointer to a column of a natural join (or its operand)
182  NULL No memory to allocate the column
183 */
184 
185 Natural_join_column *
186 Field_iterator_table_ref::get_or_create_column_ref(TableList *parent_table_ref)
187 {
188  Natural_join_column *nj_col;
189  bool is_created= true;
190  uint32_t field_count=0;
191  TableList *add_table_ref= parent_table_ref ?
192  parent_table_ref : table_ref;
193 
194  if (field_it == &table_field_it)
195  {
196  /* The field belongs to a stored table. */
197  Field *tmp_field= table_field_it.field();
198  nj_col= new Natural_join_column(tmp_field, table_ref);
199  field_count= table_ref->table->getShare()->sizeFields();
200  }
201  else
202  {
203  /*
204  The field belongs to a NATURAL join, therefore the column reference was
205  already created via one of the two constructor calls above. In this case
206  we just return the already created column reference.
207  */
208  assert(table_ref->is_join_columns_complete);
209  is_created= false;
210  nj_col= natural_join_it.column_ref();
211  assert(nj_col);
212  }
213  assert(!nj_col->table_field ||
214  nj_col->table_ref->table == nj_col->table_field->getTable());
215 
216  /*
217  If the natural join column was just created add it to the list of
218  natural join columns of either 'parent_table_ref' or to the table
219  reference that directly contains the original field.
220  */
221  if (is_created)
222  {
223  /* Make sure not all columns were materialized. */
224  assert(!add_table_ref->is_join_columns_complete);
225  if (!add_table_ref->join_columns)
226  {
227  /* Create a list of natural join columns on demand. */
228  add_table_ref->join_columns= new List<Natural_join_column>;
229  add_table_ref->is_join_columns_complete= false;
230  }
231  add_table_ref->join_columns->push_back(nj_col);
232  /*
233  If new fields are added to their original table reference, mark if
234  all fields were added. We do it here as the caller has no easy way
235  of knowing when to do it.
236  If the fields are being added to parent_table_ref, then the caller
237  must take care to mark when all fields are created/added.
238  */
239  if (!parent_table_ref &&
240  add_table_ref->join_columns->size() == field_count)
241  add_table_ref->is_join_columns_complete= true;
242  }
243 
244  return nj_col;
245 }
246 
247 
248 /*
249  Return an existing reference to a column of a natural/using join.
250 
251  SYNOPSIS
252  Field_iterator_table_ref::get_natural_column_ref()
253 
254  DESCRIPTION
255  The method should be called in contexts where it is expected that
256  all natural join columns are already created, and that the column
257  being retrieved is a Natural_join_column.
258 
259  RETURN
260  # Pointer to a column of a natural join (or its operand)
261  NULL No memory to allocate the column
262 */
263 
264 Natural_join_column *
265 Field_iterator_table_ref::get_natural_column_ref()
266 {
267  assert(field_it == &natural_join_it);
268  /*
269  The field belongs to a NATURAL join, therefore the column reference was
270  already created via one of the two constructor calls above. In this case
271  we just return the already created column reference.
272  */
273  Natural_join_column* nj_col= natural_join_it.column_ref();
274  assert(nj_col && (!nj_col->table_field || nj_col->table_ref->table == nj_col->table_field->getTable()));
275  return nj_col;
276 }
277 
278 } /* namespace drizzled */
TODO: Rename this file - func.h is stupid.
Table * table
opened table
Definition: table_list.h:145
TableList * first_leaf_for_name_resolution()
Definition: table_list.cc:107
Table * table
Definition: field.h:81
TableList * last_leaf_for_name_resolution()
Definition: table_list.cc:69