~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_base.cc

edit

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* Basic functions needed by many modules */
18
 
#include <config.h>
 
18
#include "config.h"
19
19
#include <assert.h>
20
20
 
21
21
#include <signal.h>
30
30
#  include <time.h>
31
31
# endif
32
32
#endif
33
 
#include <drizzled/internal/my_pthread.h>
34
 
#include <drizzled/internal/thread_var.h>
 
33
#include "drizzled/internal/my_pthread.h"
 
34
#include "drizzled/internal/thread_var.h"
35
35
 
36
36
#include <drizzled/sql_select.h>
37
37
#include <drizzled/error.h>
44
44
#include <drizzled/check_stack_overrun.h>
45
45
#include <drizzled/lock.h>
46
46
#include <drizzled/plugin/listen.h>
47
 
#include <drizzled/cached_directory.h>
 
47
#include "drizzled/cached_directory.h"
48
48
#include <drizzled/field/epoch.h>
49
49
#include <drizzled/field/null.h>
50
 
#include <drizzled/sql_table.h>
51
 
#include <drizzled/global_charset_info.h>
52
 
#include <drizzled/pthread_globals.h>
53
 
#include <drizzled/internal/iocache.h>
54
 
#include <drizzled/drizzled.h>
55
 
#include <drizzled/plugin/authorization.h>
56
 
#include <drizzled/table/temporary.h>
57
 
#include <drizzled/table/placeholder.h>
58
 
#include <drizzled/table/unused.h>
59
 
#include <drizzled/plugin/storage_engine.h>
60
 
#include <drizzled/session.h>
61
 
 
62
 
#include <drizzled/refresh_version.h>
 
50
#include "drizzled/sql_table.h"
 
51
#include "drizzled/global_charset_info.h"
 
52
#include "drizzled/pthread_globals.h"
 
53
#include "drizzled/internal/iocache.h"
 
54
#include "drizzled/drizzled.h"
 
55
#include "drizzled/plugin/authorization.h"
 
56
#include "drizzled/table/temporary.h"
 
57
#include "drizzled/table/placeholder.h"
 
58
#include "drizzled/table/unused.h"
63
59
 
64
60
using namespace std;
65
61
 
148
144
  if (sort.io_cache)
149
145
  {
150
146
    sort.io_cache->close_cached_file();
151
 
    safe_delete(sort.io_cache);
 
147
    delete sort.io_cache;
 
148
    sort.io_cache= 0;
152
149
  }
153
150
}
154
151
 
578
575
}
579
576
 
580
577
int Open_tables_state::doGetTableDefinition(const identifier::Table &identifier,
581
 
                                            message::Table &table_proto)
 
578
                                  message::Table &table_proto)
582
579
{
583
580
  for (Table *table= getTemporaryTables() ; table ; table= table->getNext())
584
581
  {
586
583
    {
587
584
      if (identifier.getKey() == table->getShare()->getCacheKey())
588
585
      {
589
 
        table_proto.CopyFrom(*(table->getShare()->getTableMessage()));
 
586
        table_proto.CopyFrom(*(table->getShare()->getTableProto()));
590
587
 
591
588
        return EEXIST;
592
589
      }
807
804
 
808
805
  if (not table::Cache::singleton().insert(table))
809
806
  {
810
 
    safe_delete(table);
 
807
    delete table;
811
808
 
812
809
    return NULL;
813
810
  }
953
950
  {
954
951
    if (flags & DRIZZLE_OPEN_TEMPORARY_ONLY)
955
952
    {
956
 
      my_error(ER_TABLE_UNKNOWN, identifier);
 
953
      my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->getSchemaName(), table_list->getTableName());
957
954
      return NULL;
958
955
    }
959
956
 
1004
1001
    */
1005
1002
 
1006
1003
    {
1007
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1004
      table::Cache::singleton().mutex().lock(); /* Lock for FLUSH TABLES for open table */
1008
1005
 
1009
1006
      /*
1010
1007
        Actually try to find the table in the open_cache.
1056
1053
          /* Avoid self-deadlocks by detecting self-dependencies. */
1057
1054
          if (table->open_placeholder && table->in_use == this)
1058
1055
          {
 
1056
            table::Cache::singleton().mutex().unlock();
1059
1057
            my_error(ER_UPDATE_TABLE_USED, MYF(0), table->getShare()->getTableName());
1060
1058
            return NULL;
1061
1059
          }
1090
1088
          {
1091
1089
            /* wait_for_conditionwill unlock table::Cache::singleton().mutex() for us */
1092
1090
            wait_for_condition(table::Cache::singleton().mutex(), COND_refresh);
1093
 
            scopedLock.release();
1094
1091
          }
1095
1092
          else
1096
1093
          {
1097
 
            scopedLock.unlock();
 
1094
            table::Cache::singleton().mutex().unlock();
1098
1095
          }
1099
 
 
1100
1096
          /*
1101
1097
            There is a refresh in progress for this table.
1102
1098
            Signal the caller that it has to try again.
1103
1099
          */
1104
1100
          if (refresh)
1105
1101
            *refresh= true;
1106
 
 
1107
1102
          return NULL;
1108
1103
        }
1109
1104
      }
1110
 
 
1111
1105
      if (table)
1112
1106
      {
1113
1107
        table::getUnused().unlink(static_cast<table::Concurrent *>(table));
1131
1125
            */
1132
1126
            if (!(table= table_cache_insert_placeholder(lock_table_identifier)))
1133
1127
            {
 
1128
              table::Cache::singleton().mutex().unlock();
1134
1129
              return NULL;
1135
1130
            }
1136
1131
            /*
1141
1136
            table->open_placeholder= true;
1142
1137
            table->setNext(open_tables);
1143
1138
            open_tables= table;
 
1139
            table::Cache::singleton().mutex().unlock();
1144
1140
 
1145
1141
            return table ;
1146
1142
          }
1153
1149
          table= new_table;
1154
1150
          if (new_table == NULL)
1155
1151
          {
 
1152
            table::Cache::singleton().mutex().unlock();
1156
1153
            return NULL;
1157
1154
          }
1158
1155
 
1160
1157
          if (error != 0)
1161
1158
          {
1162
1159
            delete new_table;
 
1160
            table::Cache::singleton().mutex().unlock();
1163
1161
            return NULL;
1164
1162
          }
1165
1163
          (void)table::Cache::singleton().insert(new_table);
1166
1164
        }
1167
1165
      }
 
1166
 
 
1167
      table::Cache::singleton().mutex().unlock();
1168
1168
    }
1169
 
 
1170
1169
    if (refresh)
1171
1170
    {
1172
1171
      table->setNext(open_tables); /* Link into simple list */
1598
1597
     * table/schema information via error messages
1599
1598
     */
1600
1599
    identifier::Table the_table(tables->getSchemaName(), tables->getTableName());
1601
 
    if (not plugin::Authorization::isAuthorized(*user(), the_table))
 
1600
    if (not plugin::Authorization::isAuthorized(user(), the_table))
1602
1601
    {
1603
1602
      result= -1;                               // Fatal error
1604
1603
      break;
1761
1760
  Table **start,**ptr;
1762
1761
  uint32_t lock_flag= DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN;
1763
1762
 
1764
 
  if (!(ptr=start=(Table**) session->getMemRoot()->allocate(sizeof(Table*)*count)))
 
1763
  if (!(ptr=start=(Table**) session->alloc(sizeof(Table*)*count)))
1765
1764
    return -1;
1766
1765
 
1767
1766
  for (table= tables; table; table= table->next_global)
1929
1928
                           const char *name, uint32_t , Item **,
1930
1929
                           bool, TableList **actual_table)
1931
1930
{
1932
 
  List<Natural_join_column>::iterator
1933
 
    field_it(table_ref->join_columns->begin());
 
1931
  List_iterator_fast<Natural_join_column>
 
1932
    field_it(*(table_ref->join_columns));
1934
1933
  Natural_join_column *nj_col, *curr_nj_col;
1935
1934
  Field *found_field;
1936
1935
 
1944
1943
    {
1945
1944
      if (nj_col)
1946
1945
      {
1947
 
        my_error(ER_NON_UNIQ_ERROR, MYF(0), name, session->where());
 
1946
        my_error(ER_NON_UNIQ_ERROR, MYF(0), name, session->where);
1948
1947
        return NULL;
1949
1948
      }
1950
1949
      nj_col= curr_nj_col;
2145
2144
    */
2146
2145
    if (table_name && table_name[0])
2147
2146
    {
2148
 
      List<TableList>::iterator it(table_list->getNestedJoin()->join_list.begin());
 
2147
      List_iterator<TableList> it(table_list->getNestedJoin()->join_list);
2149
2148
      TableList *table;
2150
2149
      while ((table= it++))
2151
2150
      {
2295
2294
        fields.
2296
2295
      */
2297
2296
      {
2298
 
        Select_Lex *current_sel= session->getLex()->current_select;
 
2297
        Select_Lex *current_sel= session->lex->current_select;
2299
2298
        Select_Lex *last_select= table_ref->select_lex;
2300
2299
        /*
2301
2300
          If the field was an outer referencee, mark all selects using this
2341
2340
      */
2342
2341
      item->cached_table= found ?  0 : actual_table;
2343
2342
 
2344
 
      assert(session->where());
 
2343
      assert(session->where);
2345
2344
      /*
2346
2345
        If we found a fully qualified field we return it directly as it can't
2347
2346
        have duplicates.
2354
2353
        if (report_error == REPORT_ALL_ERRORS ||
2355
2354
            report_error == IGNORE_EXCEPT_NON_UNIQUE)
2356
2355
          my_error(ER_NON_UNIQ_ERROR, MYF(0),
2357
 
                   table_name ? item->full_name() : name, session->where());
 
2356
                   table_name ? item->full_name() : name, session->where);
2358
2357
        return (Field*) 0;
2359
2358
      }
2360
2359
      found= cur_field;
2387
2386
      strcat(buff, table_name);
2388
2387
      table_name=buff;
2389
2388
    }
2390
 
    my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, session->where());
 
2389
    my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, session->where);
2391
2390
  }
2392
2391
  else
2393
2392
  {
2394
2393
    if (report_error == REPORT_ALL_ERRORS ||
2395
2394
        report_error == REPORT_EXCEPT_NON_UNIQUE)
2396
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), session->where());
 
2395
      my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), session->where);
2397
2396
    else
2398
2397
      found= not_found_field;
2399
2398
  }
2444
2443
                  find_item_error_report_type report_error,
2445
2444
                  enum_resolution_type *resolution)
2446
2445
{
2447
 
  List<Item>::iterator li(items.begin());
 
2446
  List_iterator<Item> li(items);
2448
2447
  Item **found=0, **found_unaliased= 0, *item;
2449
2448
  const char *db_name=0;
2450
2449
  const char *field_name=0;
2520
2519
            */
2521
2520
            if (report_error != IGNORE_ERRORS)
2522
2521
              my_error(ER_NON_UNIQ_ERROR, MYF(0),
2523
 
                       find->full_name(), session->where());
 
2522
                       find->full_name(), session->where);
2524
2523
            return (Item**) 0;
2525
2524
          }
2526
2525
          found_unaliased= li.ref();
2551
2550
              continue;                           // Same field twice
2552
2551
            if (report_error != IGNORE_ERRORS)
2553
2552
              my_error(ER_NON_UNIQ_ERROR, MYF(0),
2554
 
                       find->full_name(), session->where());
 
2553
                       find->full_name(), session->where);
2555
2554
            return (Item**) 0;
2556
2555
          }
2557
2556
          found= li.ref();
2603
2602
    {
2604
2603
      if (report_error != IGNORE_ERRORS)
2605
2604
        my_error(ER_NON_UNIQ_ERROR, MYF(0),
2606
 
                 find->full_name(), session->where());
 
2605
                 find->full_name(), session->where);
2607
2606
      return (Item **) 0;
2608
2607
    }
2609
2608
    if (found_unaliased)
2619
2618
  {
2620
2619
    if (report_error == REPORT_ALL_ERRORS)
2621
2620
      my_error(ER_BAD_FIELD_ERROR, MYF(0),
2622
 
               find->full_name(), session->where());
 
2621
               find->full_name(), session->where);
2623
2622
    return (Item **) 0;
2624
2623
  }
2625
2624
  else
2647
2646
static bool
2648
2647
test_if_string_in_list(const char *find, List<String> *str_list)
2649
2648
{
2650
 
  List<String>::iterator str_list_it(str_list->begin());
 
2649
  List_iterator<String> str_list_it(*str_list);
2651
2650
  String *curr_str;
2652
2651
  size_t find_length= strlen(find);
2653
2652
  while ((curr_str= str_list_it++))
2790
2789
        if (cur_nj_col_2->is_common ||
2791
2790
            (found && (!using_fields || is_using_column_1)))
2792
2791
        {
2793
 
          my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, session->where());
 
2792
          my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, session->where);
2794
2793
          return(result);
2795
2794
        }
2796
2795
        nj_col_2= cur_nj_col_2;
2981
2980
  if (using_fields && found_using_fields < using_fields->elements)
2982
2981
  {
2983
2982
    String *using_field_name;
2984
 
    List<String>::iterator using_fields_it(using_fields->begin());
 
2983
    List_iterator_fast<String> using_fields_it(*using_fields);
2985
2984
    while ((using_field_name= using_fields_it++))
2986
2985
    {
2987
2986
      const char *using_field_name_ptr= using_field_name->c_ptr();
2988
 
      List<Natural_join_column>::iterator
2989
 
        it(natural_using_join->join_columns->begin());
 
2987
      List_iterator_fast<Natural_join_column>
 
2988
        it(*(natural_using_join->join_columns));
2990
2989
      Natural_join_column *common_field;
2991
2990
 
2992
2991
      for (;;)
2995
2994
        if (!(common_field= it++))
2996
2995
        {
2997
2996
          my_error(ER_BAD_FIELD_ERROR, MYF(0), using_field_name_ptr,
2998
 
                   session->where());
 
2997
                   session->where);
2999
2998
          return(result);
3000
2999
        }
3001
3000
        if (!my_strcasecmp(system_charset_info,
3068
3067
  /* Call the procedure recursively for each nested table reference. */
3069
3068
  if (table_ref->getNestedJoin())
3070
3069
  {
3071
 
    List<TableList>::iterator nested_it(table_ref->getNestedJoin()->join_list.begin());
 
3070
    List_iterator_fast<TableList> nested_it(table_ref->getNestedJoin()->join_list);
3072
3071
    TableList *same_level_left_neighbor= nested_it++;
3073
3072
    TableList *same_level_right_neighbor= NULL;
3074
3073
    /* Left/right-most neighbors, possibly at higher levels in the join tree. */
3122
3121
  {
3123
3122
    assert(table_ref->getNestedJoin() &&
3124
3123
           table_ref->getNestedJoin()->join_list.elements == 2);
3125
 
    List<TableList>::iterator operand_it(table_ref->getNestedJoin()->join_list.begin());
 
3124
    List_iterator_fast<TableList> operand_it(table_ref->getNestedJoin()->join_list);
3126
3125
    /*
3127
3126
      Notice that the order of join operands depends on whether table_ref
3128
3127
      represents a LEFT or a RIGHT join. In a RIGHT join, the operands are
3218
3217
                                         List<TableList> *from_clause,
3219
3218
                                         Name_resolution_context *context)
3220
3219
{
3221
 
  session->setWhere("from clause");
 
3220
  session->where= "from clause";
3222
3221
  if (from_clause->elements == 0)
3223
3222
    return false; /* We come here in the case of UNIONs. */
3224
3223
 
3225
 
  List<TableList>::iterator table_ref_it(from_clause->begin());
 
3224
  List_iterator_fast<TableList> table_ref_it(*from_clause);
3226
3225
  TableList *table_ref; /* Current table reference. */
3227
3226
  /* Table reference to the left of the current. */
3228
3227
  TableList *left_neighbor;
3272
3271
    return 0;
3273
3272
 
3274
3273
  Item *item;
3275
 
  List<Item>::iterator it(fields.begin());
 
3274
  List_iterator<Item> it(fields);
3276
3275
 
3277
 
  session->getLex()->current_select->cur_pos_in_select_list= 0;
 
3276
  session->lex->current_select->cur_pos_in_select_list= 0;
3278
3277
  while (wild_num && (item= it++))
3279
3278
  {
3280
3279
    if (item->type() == Item::FIELD_ITEM &&
3284
3283
    {
3285
3284
      uint32_t elem= fields.elements;
3286
3285
      bool any_privileges= ((Item_field *) item)->any_privileges;
3287
 
      Item_subselect *subsel= session->getLex()->current_select->master_unit()->item;
 
3286
      Item_subselect *subsel= session->lex->current_select->master_unit()->item;
3288
3287
      if (subsel &&
3289
3288
          subsel->substype() == Item_subselect::EXISTS_SUBS)
3290
3289
      {
3315
3314
      wild_num--;
3316
3315
    }
3317
3316
    else
3318
 
      session->getLex()->current_select->cur_pos_in_select_list++;
 
3317
      session->lex->current_select->cur_pos_in_select_list++;
3319
3318
  }
3320
 
  session->getLex()->current_select->cur_pos_in_select_list= UNDEF_POS;
 
3319
  session->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
3321
3320
 
3322
3321
  return 0;
3323
3322
}
3332
3331
{
3333
3332
  register Item *item;
3334
3333
  enum_mark_columns save_mark_used_columns= session->mark_used_columns;
3335
 
  nesting_map save_allow_sum_func= session->getLex()->allow_sum_func;
3336
 
  List<Item>::iterator it(fields.begin());
 
3334
  nesting_map save_allow_sum_func= session->lex->allow_sum_func;
 
3335
  List_iterator<Item> it(fields);
3337
3336
  bool save_is_item_list_lookup;
3338
3337
 
3339
3338
  session->mark_used_columns= mark_used_columns;
3340
3339
  if (allow_sum_func)
3341
 
    session->getLex()->allow_sum_func|= 1 << session->getLex()->current_select->nest_level;
3342
 
  session->setWhere(Session::DEFAULT_WHERE);
3343
 
  save_is_item_list_lookup= session->getLex()->current_select->is_item_list_lookup;
3344
 
  session->getLex()->current_select->is_item_list_lookup= 0;
 
3340
    session->lex->allow_sum_func|= 1 << session->lex->current_select->nest_level;
 
3341
  session->where= Session::DEFAULT_WHERE;
 
3342
  save_is_item_list_lookup= session->lex->current_select->is_item_list_lookup;
 
3343
  session->lex->current_select->is_item_list_lookup= 0;
3345
3344
 
3346
3345
  /*
3347
3346
    To prevent fail on forward lookup we fill it with zerows,
3351
3350
    There is other way to solve problem: fill array with pointers to list,
3352
3351
    but it will be slower.
3353
3352
 
3354
 
    TODO-> remove it when (if) we made one list for allfields and ref_pointer_array
 
3353
TODO: remove it when (if) we made one list for allfields and
 
3354
ref_pointer_array
3355
3355
  */
3356
3356
  if (ref_pointer_array)
3357
 
  {
3358
3357
    memset(ref_pointer_array, 0, sizeof(Item *) * fields.elements);
3359
 
  }
3360
3358
 
3361
3359
  Item **ref= ref_pointer_array;
3362
 
  session->getLex()->current_select->cur_pos_in_select_list= 0;
 
3360
  session->lex->current_select->cur_pos_in_select_list= 0;
3363
3361
  while ((item= it++))
3364
3362
  {
3365
3363
    if ((!item->fixed && item->fix_fields(session, it.ref())) || (item= *(it.ref()))->check_cols(1))
3366
3364
    {
3367
 
      session->getLex()->current_select->is_item_list_lookup= save_is_item_list_lookup;
3368
 
      session->getLex()->allow_sum_func= save_allow_sum_func;
 
3365
      session->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
 
3366
      session->lex->allow_sum_func= save_allow_sum_func;
3369
3367
      session->mark_used_columns= save_mark_used_columns;
3370
3368
      return true;
3371
3369
    }
3375
3373
        sum_func_list)
3376
3374
      item->split_sum_func(session, ref_pointer_array, *sum_func_list);
3377
3375
    session->used_tables|= item->used_tables();
3378
 
    session->getLex()->current_select->cur_pos_in_select_list++;
 
3376
    session->lex->current_select->cur_pos_in_select_list++;
3379
3377
  }
3380
 
  session->getLex()->current_select->is_item_list_lookup= save_is_item_list_lookup;
3381
 
  session->getLex()->current_select->cur_pos_in_select_list= UNDEF_POS;
 
3378
  session->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
 
3379
  session->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
3382
3380
 
3383
 
  session->getLex()->allow_sum_func= save_allow_sum_func;
 
3381
  session->lex->allow_sum_func= save_allow_sum_func;
3384
3382
  session->mark_used_columns= save_mark_used_columns;
3385
3383
  return(test(session->is_error()));
3386
3384
}
3549
3547
 
3550
3548
bool
3551
3549
insert_fields(Session *session, Name_resolution_context *context, const char *db_name,
3552
 
              const char *table_name, List<Item>::iterator *it,
 
3550
              const char *table_name, List_iterator<Item> *it,
3553
3551
              bool )
3554
3552
{
3555
3553
  Field_iterator_table_ref field_iterator;
3656
3654
        session->used_tables|= item->used_tables();
3657
3655
      }
3658
3656
 
3659
 
      session->getLex()->current_select->cur_pos_in_select_list++;
 
3657
      session->lex->current_select->cur_pos_in_select_list++;
3660
3658
    }
3661
3659
    /*
3662
3660
      In case of stored tables, all fields are considered as used,
3709
3707
int Session::setup_conds(TableList *leaves, COND **conds)
3710
3708
{
3711
3709
  Session *session= this;
3712
 
  Select_Lex *select_lex= session->getLex()->current_select;
 
3710
  Select_Lex *select_lex= session->lex->current_select;
3713
3711
  TableList *table= NULL;       // For HP compilers
3714
3712
  void *save_session_marker= session->session_marker;
3715
3713
  /*
3731
3729
  session->session_marker= (void*)1;
3732
3730
  if (*conds)
3733
3731
  {
3734
 
    session->setWhere("where clause");
 
3732
    session->where="where clause";
3735
3733
    if ((!(*conds)->fixed && (*conds)->fix_fields(session, conds)) ||
3736
3734
        (*conds)->check_cols(1))
3737
3735
      goto err_no_arena;
3753
3751
      {
3754
3752
        /* Make a join an a expression */
3755
3753
        session->session_marker= (void*)embedded;
3756
 
        session->setWhere("on clause");
 
3754
        session->where="on clause";
3757
3755
        if ((!embedded->on_expr->fixed && embedded->on_expr->fix_fields(session, &embedded->on_expr)) ||
3758
3756
            embedded->on_expr->check_cols(1))
3759
3757
          goto err_no_arena;
3767
3765
  }
3768
3766
  session->session_marker= save_session_marker;
3769
3767
 
3770
 
  session->getLex()->current_select->is_item_list_lookup= save_is_item_list_lookup;
 
3768
  session->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
3771
3769
  return(test(session->is_error()));
3772
3770
 
3773
3771
err_no_arena:
3805
3803
bool
3806
3804
fill_record(Session *session, List<Item> &fields, List<Item> &values, bool ignore_errors)
3807
3805
{
3808
 
  List<Item>::iterator f(fields.begin());
3809
 
  List<Item>::iterator v(values.begin());
 
3806
  List_iterator_fast<Item> f(fields),v(values);
3810
3807
  Item *value;
3811
3808
  Item_field *field;
3812
3809
  Table *table;
3824
3821
    field= static_cast<Item_field *>(f++);
3825
3822
    table= field->field->getTable();
3826
3823
    table->auto_increment_field_not_null= false;
3827
 
    f= fields.begin();
 
3824
    f.rewind();
3828
3825
  }
3829
3826
 
3830
3827
  while ((field= static_cast<Item_field *>(f++)))
3871
3868
 
3872
3869
bool fill_record(Session *session, Field **ptr, List<Item> &values, bool)
3873
3870
{
3874
 
  List<Item>::iterator v(values.begin());
 
3871
  List_iterator_fast<Item> v(values);
3875
3872
  Item *value;
3876
3873
  Table *table= 0;
3877
3874
  Field *field;