~drizzle-trunk/drizzle/development

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