~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field_iterator.cc

  • Committer: Brian Aker
  • Date: 2010-01-22 00:53:13 UTC
  • Revision ID: brian@gaz-20100122005313-jmizcbcdi1lt4tcx
Revert db patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
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/table.h>
 
25
 
 
26
const char *Field_iterator_table::name()
 
27
{
 
28
  return (*ptr)->field_name;
 
29
}
 
30
 
 
31
 
 
32
void Field_iterator_table::set(TableList *table)
 
33
{
 
34
  ptr= table->table->field;
 
35
}
 
36
 
 
37
 
 
38
void Field_iterator_table::set_table(Table *table)
 
39
{
 
40
  ptr= table->field;
 
41
}
 
42
 
 
43
 
 
44
Item *Field_iterator_table::create_item(Session *session)
 
45
{
 
46
  Select_Lex *select= session->lex->current_select;
 
47
 
 
48
  Item_field *item= new Item_field(session, &select->context, *ptr);
 
49
 
 
50
  return item;
 
51
}
 
52
 
 
53
 
 
54
void Field_iterator_natural_join::set(TableList *table_ref)
 
55
{
 
56
  assert(table_ref->join_columns);
 
57
  column_ref_it.init(*(table_ref->join_columns));
 
58
  cur_column_ref= column_ref_it++;
 
59
}
 
60
 
 
61
 
 
62
void Field_iterator_natural_join::next()
 
63
{
 
64
  cur_column_ref= column_ref_it++;
 
65
  assert(!cur_column_ref || ! cur_column_ref->table_field ||
 
66
              cur_column_ref->table_ref->table ==
 
67
              cur_column_ref->table_field->table);
 
68
}
 
69
 
 
70
 
 
71
void Field_iterator_table_ref::set_field_iterator()
 
72
{
 
73
  /*
 
74
    If the table reference we are iterating over is a natural join, or it is
 
75
    an operand of a natural join, and TableList::join_columns contains all
 
76
    the columns of the join operand, then we pick the columns from
 
77
    TableList::join_columns, instead of the  orginial container of the
 
78
    columns of the join operator.
 
79
  */
 
80
  if (table_ref->is_join_columns_complete)
 
81
  {
 
82
    field_it= &natural_join_it;
 
83
  }
 
84
  /* This is a base table or stored view. */
 
85
  else
 
86
  {
 
87
    assert(table_ref->table);
 
88
    field_it= &table_field_it;
 
89
  }
 
90
  field_it->set(table_ref);
 
91
  return;
 
92
}
 
93
 
 
94
 
 
95
void Field_iterator_table_ref::set(TableList *table)
 
96
{
 
97
  assert(table);
 
98
  first_leaf= table->first_leaf_for_name_resolution();
 
99
  last_leaf=  table->last_leaf_for_name_resolution();
 
100
  assert(first_leaf && last_leaf);
 
101
  table_ref= first_leaf;
 
102
  set_field_iterator();
 
103
}
 
104
 
 
105
 
 
106
void Field_iterator_table_ref::next()
 
107
{
 
108
  /* Move to the next field in the current table reference. */
 
109
  field_it->next();
 
110
  /*
 
111
    If all fields of the current table reference are exhausted, move to
 
112
    the next leaf table reference.
 
113
  */
 
114
  if (field_it->end_of_fields() && table_ref != last_leaf)
 
115
  {
 
116
    table_ref= table_ref->next_name_resolution_table;
 
117
    assert(table_ref);
 
118
    set_field_iterator();
 
119
  }
 
120
}
 
121
 
 
122
 
 
123
const char *Field_iterator_table_ref::table_name()
 
124
{
 
125
  if (table_ref->is_natural_join)
 
126
    return natural_join_it.column_ref()->table_name();
 
127
 
 
128
  assert(!strcmp(table_ref->table_name,
 
129
                      table_ref->table->s->table_name.str));
 
130
  return table_ref->table_name;
 
131
}
 
132
 
 
133
 
 
134
const char *Field_iterator_table_ref::db_name()
 
135
{
 
136
  if (table_ref->is_natural_join)
 
137
    return natural_join_it.column_ref()->db_name();
 
138
 
 
139
  /*
 
140
    Test that TableList::db is the same as TableShare::db to
 
141
    ensure consistency. 
 
142
  */
 
143
  assert(!strcmp(table_ref->db, table_ref->table->s->db.str));
 
144
  return table_ref->db;
 
145
}
 
146
 
 
147
 
 
148
 
 
149
/*
 
150
  Create new or return existing column reference to a column of a
 
151
  natural/using join.
 
152
 
 
153
  SYNOPSIS
 
154
    Field_iterator_table_ref::get_or_create_column_ref()
 
155
    parent_table_ref  the parent table reference over which the
 
156
                      iterator is iterating
 
157
 
 
158
  DESCRIPTION
 
159
    Create a new natural join column for the current field of the
 
160
    iterator if no such column was created, or return an already
 
161
    created natural join column. The former happens for base tables or
 
162
    views, and the latter for natural/using joins. If a new field is
 
163
    created, then the field is added to 'parent_table_ref' if it is
 
164
    given, or to the original table referene of the field if
 
165
    parent_table_ref == NULL.
 
166
 
 
167
  NOTES
 
168
    This method is designed so that when a Field_iterator_table_ref
 
169
    walks through the fields of a table reference, all its fields
 
170
    are created and stored as follows:
 
171
    - If the table reference being iterated is a stored table, view or
 
172
      natural/using join, store all natural join columns in a list
 
173
      attached to that table reference.
 
174
    - If the table reference being iterated is a nested join that is
 
175
      not natural/using join, then do not materialize its result
 
176
      fields. This is OK because for such table references
 
177
      Field_iterator_table_ref iterates over the fields of the nested
 
178
      table references (recursively). In this way we avoid the storage
 
179
      of unnecessay copies of result columns of nested joins.
 
180
 
 
181
  RETURN
 
182
    #     Pointer to a column of a natural join (or its operand)
 
183
    NULL  No memory to allocate the column
 
184
*/
 
185
 
 
186
Natural_join_column *
 
187
Field_iterator_table_ref::get_or_create_column_ref(TableList *parent_table_ref)
 
188
{
 
189
  Natural_join_column *nj_col;
 
190
  bool is_created= true;
 
191
  uint32_t field_count=0;
 
192
  TableList *add_table_ref= parent_table_ref ?
 
193
                             parent_table_ref : table_ref;
 
194
 
 
195
  if (field_it == &table_field_it)
 
196
  {
 
197
    /* The field belongs to a stored table. */
 
198
    Field *tmp_field= table_field_it.field();
 
199
    nj_col= new Natural_join_column(tmp_field, table_ref);
 
200
    field_count= table_ref->table->s->fields;
 
201
  }
 
202
  else
 
203
  {
 
204
    /*
 
205
      The field belongs to a NATURAL join, therefore the column reference was
 
206
      already created via one of the two constructor calls above. In this case
 
207
      we just return the already created column reference.
 
208
    */
 
209
    assert(table_ref->is_join_columns_complete);
 
210
    is_created= false;
 
211
    nj_col= natural_join_it.column_ref();
 
212
    assert(nj_col);
 
213
  }
 
214
  assert(!nj_col->table_field ||
 
215
              nj_col->table_ref->table == nj_col->table_field->table);
 
216
 
 
217
  /*
 
218
    If the natural join column was just created add it to the list of
 
219
    natural join columns of either 'parent_table_ref' or to the table
 
220
    reference that directly contains the original field.
 
221
  */
 
222
  if (is_created)
 
223
  {
 
224
    /* Make sure not all columns were materialized. */
 
225
    assert(!add_table_ref->is_join_columns_complete);
 
226
    if (!add_table_ref->join_columns)
 
227
    {
 
228
      /* Create a list of natural join columns on demand. */
 
229
      if (!(add_table_ref->join_columns= new List<Natural_join_column>))
 
230
        return NULL;
 
231
      add_table_ref->is_join_columns_complete= false;
 
232
    }
 
233
    add_table_ref->join_columns->push_back(nj_col);
 
234
    /*
 
235
      If new fields are added to their original table reference, mark if
 
236
      all fields were added. We do it here as the caller has no easy way
 
237
      of knowing when to do it.
 
238
      If the fields are being added to parent_table_ref, then the caller
 
239
      must take care to mark when all fields are created/added.
 
240
    */
 
241
    if (!parent_table_ref &&
 
242
        add_table_ref->join_columns->elements == field_count)
 
243
      add_table_ref->is_join_columns_complete= true;
 
244
  }
 
245
 
 
246
  return nj_col;
 
247
}
 
248
 
 
249
 
 
250
/*
 
251
  Return an existing reference to a column of a natural/using join.
 
252
 
 
253
  SYNOPSIS
 
254
    Field_iterator_table_ref::get_natural_column_ref()
 
255
 
 
256
  DESCRIPTION
 
257
    The method should be called in contexts where it is expected that
 
258
    all natural join columns are already created, and that the column
 
259
    being retrieved is a Natural_join_column.
 
260
 
 
261
  RETURN
 
262
    #     Pointer to a column of a natural join (or its operand)
 
263
    NULL  No memory to allocate the column
 
264
*/
 
265
 
 
266
Natural_join_column *
 
267
Field_iterator_table_ref::get_natural_column_ref()
 
268
{
 
269
  Natural_join_column *nj_col;
 
270
 
 
271
  assert(field_it == &natural_join_it);
 
272
  /*
 
273
    The field belongs to a NATURAL join, therefore the column reference was
 
274
    already created via one of the two constructor calls above. In this case
 
275
    we just return the already created column reference.
 
276
  */
 
277
  nj_col= natural_join_it.column_ref();
 
278
  assert(nj_col &&
 
279
              (!nj_col->table_field ||
 
280
               nj_col->table_ref->table == nj_col->table_field->table));
 
281
  return nj_col;
 
282
}
 
283