~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field_iterator.cc

  • Committer: Brian Aker
  • Date: 2008-08-19 17:29:21 UTC
  • Revision ID: brian@tangent.org-20080819172921-bc3kpgsrzsdv338l
Moved Field iterator out to its own definition.

Show diffs side-by-side

added added

removed removed

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