~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
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
642.1.8 by Lee
move functions from item.cc/item.h to item directory
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;
2060 by Brian Aker
Added native functions into the function table.
250
            prev_subselect_item->const_item_cache= false;
642.1.8 by Lee
move functions from item.cc/item.h to item directory
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;
2060 by Brian Aker
Added native functions into the function table.
258
        prev_subselect_item->const_item_cache= false;
642.1.8 by Lee
move functions from item.cc/item.h to item directory
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
2030.1.4 by Brian Aker
Change my_decimal to Decimal
433
type::Decimal *Item_ref::val_decimal_result(type::Decimal *decimal_value)
642.1.8 by Lee
move functions from item.cc/item.h to item directory
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;
2008 by Brian Aker
Formatting + remove default from switch/case.
454
642.1.8 by Lee
move functions from item.cc/item.h to item directory
455
    case DECIMAL_RESULT:
2008 by Brian Aker
Formatting + remove default from switch/case.
456
      {
2030.1.4 by Brian Aker
Change my_decimal to Decimal
457
        type::Decimal decimal_value;
458
        type::Decimal *val= result_field->val_decimal(&decimal_value);
2008 by Brian Aker
Formatting + remove default from switch/case.
459
        if (val)
2034.2.4 by Brian Aker
Further encapsulation for DECIMAL.
460
          return not val->is_zero();
2008 by Brian Aker
Formatting + remove default from switch/case.
461
        return 0;
462
      }
463
642.1.8 by Lee
move functions from item.cc/item.h to item directory
464
    case REAL_RESULT:
465
    case STRING_RESULT:
466
      return result_field->val_real() != 0.0;
2008 by Brian Aker
Formatting + remove default from switch/case.
467
642.1.8 by Lee
move functions from item.cc/item.h to item directory
468
    case ROW_RESULT:
469
      assert(0);
470
    }
471
  }
2008 by Brian Aker
Formatting + remove default from switch/case.
472
642.1.8 by Lee
move functions from item.cc/item.h to item directory
473
  return val_bool();
474
}
475
476
477
double Item_ref::val_real()
478
{
479
  assert(fixed);
480
  double tmp=(*ref)->val_result();
481
  null_value=(*ref)->null_value;
482
  return tmp;
483
}
484
485
486
int64_t Item_ref::val_int()
487
{
488
  assert(fixed);
489
  int64_t tmp=(*ref)->val_int_result();
490
  null_value=(*ref)->null_value;
491
  return tmp;
492
}
493
494
495
bool Item_ref::val_bool()
496
{
497
  assert(fixed);
498
  bool tmp= (*ref)->val_bool_result();
499
  null_value= (*ref)->null_value;
500
  return tmp;
501
}
502
503
504
String *Item_ref::val_str(String* tmp)
505
{
506
  assert(fixed);
507
  tmp=(*ref)->str_result(tmp);
508
  null_value=(*ref)->null_value;
509
  return tmp;
510
}
511
512
513
bool Item_ref::is_null()
514
{
515
  assert(fixed);
516
  return (*ref)->is_null();
517
}
518
519
2030.1.5 by Brian Aker
Update for moving DRIZZLE_TIME to type::Time
520
bool Item_ref::get_date(type::Time *ltime,uint32_t fuzzydate)
642.1.8 by Lee
move functions from item.cc/item.h to item directory
521
{
522
  return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
523
}
524
525
2030.1.4 by Brian Aker
Change my_decimal to Decimal
526
type::Decimal *Item_ref::val_decimal(type::Decimal *decimal_value)
642.1.8 by Lee
move functions from item.cc/item.h to item directory
527
{
2030.1.4 by Brian Aker
Change my_decimal to Decimal
528
  type::Decimal *val= (*ref)->val_decimal_result(decimal_value);
642.1.8 by Lee
move functions from item.cc/item.h to item directory
529
  null_value= (*ref)->null_value;
530
  return val;
531
}
532
533
int Item_ref::save_in_field(Field *to, bool no_conversions)
534
{
535
  int res;
536
  assert(!result_field);
537
  res= (*ref)->save_in_field(to, no_conversions);
538
  null_value= (*ref)->null_value;
539
  return res;
540
}
541
542
543
void Item_ref::save_org_in_field(Field *field)
544
{
545
  (*ref)->save_org_in_field(field);
546
}
547
548
1052.2.4 by Nathan Williams
No actual code changes. Changed Send_field to SendField to be consistent with coding standards.
549
void Item_ref::make_field(SendField *field)
642.1.8 by Lee
move functions from item.cc/item.h to item directory
550
{
551
  (*ref)->make_field(field);
552
  /* Non-zero in case of a view */
553
  if (name)
554
    field->col_name= name;
555
  if (table_name)
556
    field->table_name= table_name;
557
  if (db_name)
558
    field->db_name= db_name;
559
}
560
561
562
Item *Item_ref::get_tmp_table_item(Session *session)
563
{
564
  if (!result_field)
565
    return (*ref)->get_tmp_table_item(session);
566
567
  Item_field *item= new Item_field(result_field);
568
  if (item)
569
  {
570
    item->table_name= table_name;
571
    item->db_name= db_name;
572
  }
573
  return item;
574
}
575
846 by Brian Aker
Removing on typedeffed class.
576
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
577
{
578
  if (depended_from == new_parent)
579
  {
580
    (*ref)->fix_after_pullout(new_parent, ref);
581
    depended_from= NULL;
582
  }
583
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
584
585
} /* namespace drizzled */