~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/item/ref.cc

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

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 <drizzled/server_includes.h>
21
 
#include CSTDINT_H
22
 
#include <drizzled/session.h>
23
 
#include <drizzled/error.h>
24
 
#include <drizzled/show.h>
25
 
#include <drizzled/item/ref.h>
26
 
 
27
 
Item_ref::Item_ref(Name_resolution_context *context_arg,
28
 
                   Item **item, const char *table_name_arg,
29
 
                   const char *field_name_arg,
30
 
                   bool alias_name_used_arg)
31
 
  :Item_ident(context_arg, NULL, table_name_arg, field_name_arg),
32
 
   result_field(0), ref(item)
33
 
{
34
 
  alias_name_used= alias_name_used_arg;
35
 
  /*
36
 
    This constructor used to create some internals references over fixed items
37
 
  */
38
 
  if (ref && *ref && (*ref)->fixed)
39
 
    set_properties();
40
 
}
41
 
 
42
 
 
43
 
/**
44
 
  Resolve the name of a reference to a column reference.
45
 
 
46
 
  The method resolves the column reference represented by 'this' as a column
47
 
  present in one of: GROUP BY clause, SELECT clause, outer queries. It is
48
 
  used typically for columns in the HAVING clause which are not under
49
 
  aggregate functions.
50
 
 
51
 
  POSTCONDITION @n
52
 
  Item_ref::ref is 0 or points to a valid item.
53
 
 
54
 
  @note
55
 
    The name resolution algorithm used is (where [T_j] is an optional table
56
 
    name that qualifies the column name):
57
 
 
58
 
  @code
59
 
        resolve_extended([T_j].col_ref_i)
60
 
        {
61
 
          Search for a column or derived column named col_ref_i [in table T_j]
62
 
          in the SELECT and GROUP clauses of Q.
63
 
 
64
 
          if such a column is NOT found AND    // Lookup in outer queries.
65
 
             there are outer queries
66
 
          {
67
 
            for each outer query Q_k beginning from the inner-most one
68
 
           {
69
 
              Search for a column or derived column named col_ref_i
70
 
              [in table T_j] in the SELECT and GROUP clauses of Q_k.
71
 
 
72
 
              if such a column is not found AND
73
 
                 - Q_k is not a group query AND
74
 
                 - Q_k is not inside an aggregate function
75
 
                 OR
76
 
                 - Q_(k-1) is not in a HAVING or SELECT clause of Q_k
77
 
              {
78
 
                search for a column or derived column named col_ref_i
79
 
                [in table T_j] in the FROM clause of Q_k;
80
 
              }
81
 
            }
82
 
          }
83
 
        }
84
 
  @endcode
85
 
  @n
86
 
    This procedure treats GROUP BY and SELECT clauses as one namespace for
87
 
    column references in HAVING. Notice that compared to
88
 
    Item_field::fix_fields, here we first search the SELECT and GROUP BY
89
 
    clauses, and then we search the FROM clause.
90
 
 
91
 
  @param[in]     session        current thread
92
 
  @param[in,out] reference  view column if this item was resolved to a
93
 
    view column
94
 
 
95
 
  @todo
96
 
    Here we could first find the field anyway, and then test this
97
 
    condition, so that we can give a better error message -
98
 
    ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
99
 
    ER_BAD_FIELD_ERROR which we produce now.
100
 
 
101
 
  @retval
102
 
    true  if error
103
 
  @retval
104
 
    false on success
105
 
*/
106
 
 
107
 
bool Item_ref::fix_fields(Session *session, Item **reference)
108
 
{
109
 
  enum_parsing_place place= NO_MATTER;
110
 
  assert(fixed == 0);
111
 
  Select_Lex *current_sel= session->lex->current_select;
112
 
 
113
 
  if (!ref || ref == not_found_item)
114
 
  {
115
 
    if (!(ref= resolve_ref_in_select_and_group(session, this,
116
 
                                               context->select_lex)))
117
 
      goto error;             /* Some error occurred (e.g. ambiguous names). */
118
 
 
119
 
    if (ref == not_found_item) /* This reference was not resolved. */
120
 
    {
121
 
      Name_resolution_context *last_checked_context= context;
122
 
      Name_resolution_context *outer_context= context->outer_context;
123
 
      Field *from_field;
124
 
      ref= 0;
125
 
 
126
 
      if (!outer_context)
127
 
      {
128
 
        /* The current reference cannot be resolved in this query. */
129
 
        my_error(ER_BAD_FIELD_ERROR,MYF(0),
130
 
                 this->full_name(), current_session->where);
131
 
        goto error;
132
 
      }
133
 
 
134
 
      /*
135
 
        If there is an outer context (select), and it is not a derived table
136
 
        (which do not support the use of outer fields for now), try to
137
 
        resolve this reference in the outer select(s).
138
 
 
139
 
        We treat each subselect as a separate namespace, so that different
140
 
        subselects may contain columns with the same names. The subselects are
141
 
        searched starting from the innermost.
142
 
      */
143
 
      from_field= (Field*) not_found_field;
144
 
 
145
 
      do
146
 
      {
147
 
        Select_Lex *select= outer_context->select_lex;
148
 
        Item_subselect *prev_subselect_item=
149
 
          last_checked_context->select_lex->master_unit()->item;
150
 
        last_checked_context= outer_context;
151
 
 
152
 
        /* Search in the SELECT and GROUP lists of the outer select. */
153
 
        if (outer_context->resolve_in_select_list)
154
 
        {
155
 
          if (!(ref= resolve_ref_in_select_and_group(session, this, select)))
156
 
            goto error; /* Some error occurred (e.g. ambiguous names). */
157
 
          if (ref != not_found_item)
158
 
          {
159
 
            assert(*ref && (*ref)->fixed);
160
 
            prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
161
 
            prev_subselect_item->const_item_cache&= (*ref)->const_item();
162
 
            break;
163
 
          }
164
 
          /*
165
 
            Set ref to 0 to ensure that we get an error in case we replaced
166
 
            this item with another item and still use this item in some
167
 
            other place of the parse tree.
168
 
          */
169
 
          ref= 0;
170
 
        }
171
 
 
172
 
        place= prev_subselect_item->parsing_place;
173
 
        /*
174
 
          Check table fields only if the subquery is used somewhere out of
175
 
          HAVING or the outer SELECT does not use grouping (i.e. tables are
176
 
          accessible).
177
 
          TODO:
178
 
          Here we could first find the field anyway, and then test this
179
 
          condition, so that we can give a better error message -
180
 
          ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
181
 
          ER_BAD_FIELD_ERROR which we produce now.
182
 
        */
183
 
        if ((place != IN_HAVING ||
184
 
             (!select->with_sum_func &&
185
 
              select->group_list.elements == 0)))
186
 
        {
187
 
          /*
188
 
            In case of view, find_field_in_tables() write pointer to view
189
 
            field expression to 'reference', i.e. it substitute that
190
 
            expression instead of this Item_ref
191
 
          */
192
 
          from_field= find_field_in_tables(session, this,
193
 
                                           outer_context->
194
 
                                             first_name_resolution_table,
195
 
                                           outer_context->
196
 
                                             last_name_resolution_table,
197
 
                                           reference,
198
 
                                           IGNORE_EXCEPT_NON_UNIQUE,
199
 
                                           true, true);
200
 
          if (! from_field)
201
 
            goto error;
202
 
          if (from_field == view_ref_found)
203
 
          {
204
 
            Item::Type refer_type= (*reference)->type();
205
 
            prev_subselect_item->used_tables_cache|=
206
 
              (*reference)->used_tables();
207
 
            prev_subselect_item->const_item_cache&=
208
 
              (*reference)->const_item();
209
 
            assert((*reference)->type() == REF_ITEM);
210
 
            mark_as_dependent(session, last_checked_context->select_lex,
211
 
                              context->select_lex, this,
212
 
                              ((refer_type == REF_ITEM ||
213
 
                                refer_type == FIELD_ITEM) ?
214
 
                               (Item_ident*) (*reference) :
215
 
                               0));
216
 
            /*
217
 
              view reference found, we substituted it instead of this
218
 
              Item, so can quit
219
 
            */
220
 
            return false;
221
 
          }
222
 
          if (from_field != not_found_field)
223
 
          {
224
 
            if (cached_table && cached_table->select_lex &&
225
 
                outer_context->select_lex &&
226
 
                cached_table->select_lex != outer_context->select_lex)
227
 
            {
228
 
              /*
229
 
                Due to cache, find_field_in_tables() can return field which
230
 
                doesn't belong to provided outer_context. In this case we have
231
 
                to find proper field context in order to fix field correcly.
232
 
              */
233
 
              do
234
 
              {
235
 
                outer_context= outer_context->outer_context;
236
 
                select= outer_context->select_lex;
237
 
                prev_subselect_item=
238
 
                  last_checked_context->select_lex->master_unit()->item;
239
 
                last_checked_context= outer_context;
240
 
              } while (outer_context && outer_context->select_lex &&
241
 
                       cached_table->select_lex != outer_context->select_lex);
242
 
            }
243
 
            prev_subselect_item->used_tables_cache|= from_field->table->map;
244
 
            prev_subselect_item->const_item_cache= 0;
245
 
            break;
246
 
          }
247
 
        }
248
 
        assert(from_field == not_found_field);
249
 
 
250
 
        /* Reference is not found => depend on outer (or just error). */
251
 
        prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
252
 
        prev_subselect_item->const_item_cache= 0;
253
 
 
254
 
        outer_context= outer_context->outer_context;
255
 
      } while (outer_context);
256
 
 
257
 
      assert(from_field != 0 && from_field != view_ref_found);
258
 
      if (from_field != not_found_field)
259
 
      {
260
 
        Item_field* fld;
261
 
        if (!(fld= new Item_field(from_field)))
262
 
          goto error;
263
 
        session->change_item_tree(reference, fld);
264
 
        mark_as_dependent(session, last_checked_context->select_lex,
265
 
                          session->lex->current_select, this, fld);
266
 
        /*
267
 
          A reference is resolved to a nest level that's outer or the same as
268
 
          the nest level of the enclosing set function : adjust the value of
269
 
          max_arg_level for the function if it's needed.
270
 
        */
271
 
        if (session->lex->in_sum_func &&
272
 
            session->lex->in_sum_func->nest_level >=
273
 
            last_checked_context->select_lex->nest_level)
274
 
          set_if_bigger(session->lex->in_sum_func->max_arg_level,
275
 
                        last_checked_context->select_lex->nest_level);
276
 
        return false;
277
 
      }
278
 
      if (ref == 0)
279
 
      {
280
 
        /* The item was not a table field and not a reference */
281
 
        my_error(ER_BAD_FIELD_ERROR, MYF(0),
282
 
                 this->full_name(), current_session->where);
283
 
        goto error;
284
 
      }
285
 
      /* Should be checked in resolve_ref_in_select_and_group(). */
286
 
      assert(*ref && (*ref)->fixed);
287
 
      mark_as_dependent(session, last_checked_context->select_lex,
288
 
                        context->select_lex, this, this);
289
 
      /*
290
 
        A reference is resolved to a nest level that's outer or the same as
291
 
        the nest level of the enclosing set function : adjust the value of
292
 
        max_arg_level for the function if it's needed.
293
 
      */
294
 
      if (session->lex->in_sum_func &&
295
 
          session->lex->in_sum_func->nest_level >=
296
 
          last_checked_context->select_lex->nest_level)
297
 
        set_if_bigger(session->lex->in_sum_func->max_arg_level,
298
 
                      last_checked_context->select_lex->nest_level);
299
 
    }
300
 
  }
301
 
 
302
 
  assert(*ref);
303
 
  /*
304
 
    Check if this is an incorrect reference in a group function or forward
305
 
    reference. Do not issue an error if this is:
306
 
      1. outer reference (will be fixed later by the fix_inner_refs function);
307
 
      2. an unnamed reference inside an aggregate function.
308
 
  */
309
 
  if (!((*ref)->type() == REF_ITEM &&
310
 
       ((Item_ref *)(*ref))->ref_type() == OUTER_REF) &&
311
 
      (((*ref)->with_sum_func && name &&
312
 
        !(current_sel->linkage != GLOBAL_OPTIONS_TYPE &&
313
 
          current_sel->having_fix_field)) ||
314
 
       !(*ref)->fixed))
315
 
  {
316
 
    my_error(ER_ILLEGAL_REFERENCE, MYF(0),
317
 
             name, ((*ref)->with_sum_func?
318
 
                    "reference to group function":
319
 
                    "forward reference in item list"));
320
 
    goto error;
321
 
  }
322
 
 
323
 
  set_properties();
324
 
 
325
 
  if ((*ref)->check_cols(1))
326
 
    goto error;
327
 
  return false;
328
 
 
329
 
error:
330
 
  context->process_error(session);
331
 
  return true;
332
 
}
333
 
 
334
 
 
335
 
void Item_ref::set_properties()
336
 
{
337
 
  max_length= (*ref)->max_length;
338
 
  maybe_null= (*ref)->maybe_null;
339
 
  decimals=   (*ref)->decimals;
340
 
  collation.set((*ref)->collation);
341
 
  /*
342
 
    We have to remember if we refer to a sum function, to ensure that
343
 
    split_sum_func() doesn't try to change the reference.
344
 
  */
345
 
  with_sum_func= (*ref)->with_sum_func;
346
 
  unsigned_flag= (*ref)->unsigned_flag;
347
 
  fixed= 1;
348
 
  if (alias_name_used)
349
 
    return;
350
 
  if ((*ref)->type() == FIELD_ITEM)
351
 
    alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
352
 
  else
353
 
    alias_name_used= true; // it is not field, so it is was resolved by alias
354
 
}
355
 
 
356
 
 
357
 
void Item_ref::cleanup()
358
 
{
359
 
  Item_ident::cleanup();
360
 
  result_field= 0;
361
 
  return;
362
 
}
363
 
 
364
 
 
365
 
void Item_ref::print(String *str, enum_query_type query_type)
366
 
{
367
 
  if (ref)
368
 
  {
369
 
    if ((*ref)->type() != Item::CACHE_ITEM &&
370
 
        !table_name && name && alias_name_used)
371
 
    {
372
 
      str->append_identifier(name, (uint) strlen(name));
373
 
    }
374
 
    else
375
 
      (*ref)->print(str, query_type);
376
 
  }
377
 
  else
378
 
    Item_ident::print(str, query_type);
379
 
}
380
 
 
381
 
 
382
 
bool Item_ref::send(Protocol *prot, String *tmp)
383
 
{
384
 
  if (result_field)
385
 
    return prot->store(result_field);
386
 
  return (*ref)->send(prot, tmp);
387
 
}
388
 
 
389
 
 
390
 
double Item_ref::val_result()
391
 
{
392
 
  if (result_field)
393
 
  {
394
 
    if ((null_value= result_field->is_null()))
395
 
      return 0.0;
396
 
    return result_field->val_real();
397
 
  }
398
 
  return val_real();
399
 
}
400
 
 
401
 
 
402
 
int64_t Item_ref::val_int_result()
403
 
{
404
 
  if (result_field)
405
 
  {
406
 
    if ((null_value= result_field->is_null()))
407
 
      return 0;
408
 
    return result_field->val_int();
409
 
  }
410
 
  return val_int();
411
 
}
412
 
 
413
 
 
414
 
String *Item_ref::str_result(String* str)
415
 
{
416
 
  if (result_field)
417
 
  {
418
 
    if ((null_value= result_field->is_null()))
419
 
      return 0;
420
 
    str->set_charset(str_value.charset());
421
 
    return result_field->val_str(str, &str_value);
422
 
  }
423
 
  return val_str(str);
424
 
}
425
 
 
426
 
 
427
 
my_decimal *Item_ref::val_decimal_result(my_decimal *decimal_value)
428
 
{
429
 
  if (result_field)
430
 
  {
431
 
    if ((null_value= result_field->is_null()))
432
 
      return 0;
433
 
    return result_field->val_decimal(decimal_value);
434
 
  }
435
 
  return val_decimal(decimal_value);
436
 
}
437
 
 
438
 
 
439
 
bool Item_ref::val_bool_result()
440
 
{
441
 
  if (result_field)
442
 
  {
443
 
    if ((null_value= result_field->is_null()))
444
 
      return 0;
445
 
    switch (result_field->result_type()) {
446
 
    case INT_RESULT:
447
 
      return result_field->val_int() != 0;
448
 
    case DECIMAL_RESULT:
449
 
    {
450
 
      my_decimal decimal_value;
451
 
      my_decimal *val= result_field->val_decimal(&decimal_value);
452
 
      if (val)
453
 
        return !my_decimal_is_zero(val);
454
 
      return 0;
455
 
    }
456
 
    case REAL_RESULT:
457
 
    case STRING_RESULT:
458
 
      return result_field->val_real() != 0.0;
459
 
    case ROW_RESULT:
460
 
    default:
461
 
      assert(0);
462
 
    }
463
 
  }
464
 
  return val_bool();
465
 
}
466
 
 
467
 
 
468
 
double Item_ref::val_real()
469
 
{
470
 
  assert(fixed);
471
 
  double tmp=(*ref)->val_result();
472
 
  null_value=(*ref)->null_value;
473
 
  return tmp;
474
 
}
475
 
 
476
 
 
477
 
int64_t Item_ref::val_int()
478
 
{
479
 
  assert(fixed);
480
 
  int64_t tmp=(*ref)->val_int_result();
481
 
  null_value=(*ref)->null_value;
482
 
  return tmp;
483
 
}
484
 
 
485
 
 
486
 
bool Item_ref::val_bool()
487
 
{
488
 
  assert(fixed);
489
 
  bool tmp= (*ref)->val_bool_result();
490
 
  null_value= (*ref)->null_value;
491
 
  return tmp;
492
 
}
493
 
 
494
 
 
495
 
String *Item_ref::val_str(String* tmp)
496
 
{
497
 
  assert(fixed);
498
 
  tmp=(*ref)->str_result(tmp);
499
 
  null_value=(*ref)->null_value;
500
 
  return tmp;
501
 
}
502
 
 
503
 
 
504
 
bool Item_ref::is_null()
505
 
{
506
 
  assert(fixed);
507
 
  return (*ref)->is_null();
508
 
}
509
 
 
510
 
 
511
 
bool Item_ref::get_date(DRIZZLE_TIME *ltime,uint32_t fuzzydate)
512
 
{
513
 
  return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
514
 
}
515
 
 
516
 
 
517
 
my_decimal *Item_ref::val_decimal(my_decimal *decimal_value)
518
 
{
519
 
  my_decimal *val= (*ref)->val_decimal_result(decimal_value);
520
 
  null_value= (*ref)->null_value;
521
 
  return val;
522
 
}
523
 
 
524
 
int Item_ref::save_in_field(Field *to, bool no_conversions)
525
 
{
526
 
  int res;
527
 
  assert(!result_field);
528
 
  res= (*ref)->save_in_field(to, no_conversions);
529
 
  null_value= (*ref)->null_value;
530
 
  return res;
531
 
}
532
 
 
533
 
 
534
 
void Item_ref::save_org_in_field(Field *field)
535
 
{
536
 
  (*ref)->save_org_in_field(field);
537
 
}
538
 
 
539
 
 
540
 
void Item_ref::make_field(Send_field *field)
541
 
{
542
 
  (*ref)->make_field(field);
543
 
  /* Non-zero in case of a view */
544
 
  if (name)
545
 
    field->col_name= name;
546
 
  if (table_name)
547
 
    field->table_name= table_name;
548
 
  if (db_name)
549
 
    field->db_name= db_name;
550
 
}
551
 
 
552
 
 
553
 
Item *Item_ref::get_tmp_table_item(Session *session)
554
 
{
555
 
  if (!result_field)
556
 
    return (*ref)->get_tmp_table_item(session);
557
 
 
558
 
  Item_field *item= new Item_field(result_field);
559
 
  if (item)
560
 
  {
561
 
    item->table_name= table_name;
562
 
    item->db_name= db_name;
563
 
  }
564
 
  return item;
565
 
}
566
 
 
567
 
void Item_ref::fix_after_pullout(Select_Lex *new_parent, Item **)
568
 
{
569
 
  if (depended_from == new_parent)
570
 
  {
571
 
    (*ref)->fix_after_pullout(new_parent, ref);
572
 
    depended_from= NULL;
573
 
  }
574
 
}