~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_insert.cc

  • Committer: Brian Aker
  • Date: 2008-12-04 19:04:01 UTC
  • Revision ID: brian@tangent.org-20081204190401-0aatrta3mo36swbk
Next pass through attribute.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/* Insert of records */
18
18
 
19
 
#include "config.h"
 
19
/*
 
20
  INSERT DELAYED
 
21
 
 
22
  Drizzle has a different form of DELAYED then MySQL. DELAYED is just
 
23
  a hint to the the sorage engine (which can then do whatever it likes.
 
24
*/
 
25
#include <drizzled/server_includes.h>
20
26
#include <drizzled/sql_select.h>
21
27
#include <drizzled/show.h>
 
28
#include <drizzled/replication/mi.h>
22
29
#include <drizzled/error.h>
23
30
#include <drizzled/name_resolution_context_state.h>
 
31
#include <drizzled/slave.h>
 
32
#include <drizzled/sql_parse.h>
24
33
#include <drizzled/probes.h>
 
34
#include <drizzled/tableop_hooks.h>
25
35
#include <drizzled/sql_base.h>
26
36
#include <drizzled/sql_load.h>
27
37
#include <drizzled/field/timestamp.h>
28
 
#include <drizzled/lock.h>
29
 
#include "drizzled/sql_table.h"
30
 
#include "drizzled/pthread_globals.h"
31
 
#include "drizzled/transaction_services.h"
32
 
#include "drizzled/plugin/transactional_storage_engine.h"
33
 
 
34
 
namespace drizzled
35
 
{
36
 
 
37
 
extern plugin::StorageEngine *heap_engine;
38
 
extern plugin::StorageEngine *myisam_engine;
 
38
 
 
39
/* Define to force use of my_malloc() if the allocated memory block is big */
 
40
 
 
41
#ifndef HAVE_ALLOCA
 
42
#define my_safe_alloca(size, min_length) my_alloca(size)
 
43
#define my_safe_afree(ptr, size, min_length) my_afree(ptr)
 
44
#else
 
45
#define my_safe_alloca(size, min_length) ((size <= min_length) ? my_alloca(size) : malloc(size))
 
46
#define my_safe_afree(ptr, size, min_length) if (size > min_length) free(ptr)
 
47
#endif
 
48
 
 
49
 
39
50
 
40
51
/*
41
52
  Check if insert fields are correct.
61
72
static int check_insert_fields(Session *session, TableList *table_list,
62
73
                               List<Item> &fields, List<Item> &values,
63
74
                               bool check_unique,
64
 
                               table_map *)
 
75
                               table_map *map __attribute__((unused)))
65
76
{
66
77
  Table *table= table_list->table;
67
78
 
78
89
      No fields are provided so all fields must be provided in the values.
79
90
      Thus we set all bits in the write set.
80
91
    */
81
 
    table->setWriteSet();
 
92
    bitmap_set_all(table->write_set);
82
93
  }
83
94
  else
84
95
  {                                             // Part field list
85
 
    Select_Lex *select_lex= &session->lex->select_lex;
 
96
    SELECT_LEX *select_lex= &session->lex->select_lex;
86
97
    Name_resolution_context *context= &select_lex->context;
87
98
    Name_resolution_context_state ctx_state;
88
99
    int res;
119
130
    }
120
131
    if (table->timestamp_field) // Don't automaticly set timestamp if used
121
132
    {
122
 
      if (table->timestamp_field->isWriteSet())
 
133
      if (bitmap_is_set(table->write_set,
 
134
                        table->timestamp_field->field_index))
123
135
        clear_timestamp_auto_bits(table->timestamp_field_type,
124
136
                                  TIMESTAMP_AUTO_SET_ON_INSERT);
125
137
      else
126
138
      {
127
 
        table->setWriteSet(table->timestamp_field->field_index);
 
139
        bitmap_set_bit(table->write_set,
 
140
                       table->timestamp_field->field_index);
128
141
      }
129
142
    }
 
143
    /* Mark all virtual columns for write*/
 
144
    if (table->vfield)
 
145
      table->mark_virtual_columns();
130
146
  }
131
147
 
132
148
  return 0;
154
170
 
155
171
static int check_update_fields(Session *session, TableList *insert_table_list,
156
172
                               List<Item> &update_fields,
157
 
                               table_map *)
 
173
                               table_map *map __attribute__((unused)))
158
174
{
159
175
  Table *table= insert_table_list->table;
160
176
  bool timestamp_mark= false;
165
181
      Unmark the timestamp field so that we can check if this is modified
166
182
      by update_fields
167
183
    */
168
 
    timestamp_mark= table->write_set->testAndClear(table->timestamp_field->field_index);
 
184
    timestamp_mark= bitmap_test_and_clear(table->write_set,
 
185
                                          table->timestamp_field->field_index);
169
186
  }
170
187
 
171
188
  /* Check the fields we are going to modify */
175
192
  if (table->timestamp_field)
176
193
  {
177
194
    /* Don't set timestamp column if this is modified. */
178
 
    if (table->timestamp_field->isWriteSet())
 
195
    if (bitmap_is_set(table->write_set,
 
196
                      table->timestamp_field->field_index))
179
197
      clear_timestamp_auto_bits(table->timestamp_field_type,
180
198
                                TIMESTAMP_AUTO_SET_ON_UPDATE);
181
199
    if (timestamp_mark)
182
 
      table->setWriteSet(table->timestamp_field->field_index);
 
200
      bitmap_set_bit(table->write_set,
 
201
                     table->timestamp_field->field_index);
183
202
  }
184
203
  return 0;
185
204
}
194
213
*/
195
214
 
196
215
static
197
 
void upgrade_lock_type(Session *,
 
216
void upgrade_lock_type(Session *session __attribute__((unused)),
198
217
                       thr_lock_type *lock_type,
199
218
                       enum_duplicates duplic,
200
 
                       bool )
 
219
                       bool is_multi_insert __attribute__((unused)))
201
220
{
202
221
  if (duplic == DUP_UPDATE ||
203
222
      (duplic == DUP_REPLACE && *lock_type == TL_WRITE_CONCURRENT_INSERT))
227
246
  int error;
228
247
  bool transactional_table, joins_freed= false;
229
248
  bool changed;
 
249
  bool was_insert_delayed= (table_list->lock_type ==  TL_WRITE_DELAYED);
230
250
  uint32_t value_count;
231
251
  ulong counter = 1;
232
252
  uint64_t id;
238
258
  Name_resolution_context_state ctx_state;
239
259
  thr_lock_type lock_type;
240
260
  Item *unused_conds= 0;
241
 
 
 
261
  
242
262
 
243
263
  /*
244
264
    Upgrade lock type if the requested lock is incompatible with
247
267
  upgrade_lock_type(session, &table_list->lock_type, duplic,
248
268
                    values_list.elements > 1);
249
269
 
250
 
  if (session->openTablesLock(table_list))
 
270
  /*
 
271
    We can't write-delayed into a table locked with LOCK TABLES:
 
272
    this will lead to a deadlock, since the delayed thread will
 
273
    never be able to get a lock on the table. QQQ: why not
 
274
    upgrade the lock here instead?
 
275
  */
 
276
  if (table_list->lock_type == TL_WRITE_DELAYED && session->locked_tables &&
 
277
      find_locked_table(session, table_list->db, table_list->table_name))
251
278
  {
252
 
    DRIZZLE_INSERT_DONE(1, 0);
253
 
    return true;
 
279
    my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
 
280
             table_list->table_name);
 
281
    return(true);
254
282
  }
255
283
 
 
284
  {
 
285
    if (open_and_lock_tables(session, table_list))
 
286
      return(true);
 
287
  }
256
288
  lock_type= table_list->lock_type;
257
289
 
258
290
  session->set_proc_info("init");
302
334
      goto abort;
303
335
  }
304
336
  its.rewind ();
305
 
 
 
337
 
306
338
  /* Restore the current context. */
307
339
  ctx_state.restore_state(context, table_list);
308
340
 
309
341
  /*
310
 
    Fill in the given fields and dump it to the table cursor
 
342
    Fill in the given fields and dump it to the table file
311
343
  */
312
344
  memset(&info, 0, sizeof(info));
313
345
  info.ignore= ignore;
321
353
    to NULL.
322
354
  */
323
355
  session->count_cuted_fields= ((values_list.elements == 1 &&
324
 
                                 !ignore) ?
325
 
                                CHECK_FIELD_ERROR_FOR_NULL :
326
 
                                CHECK_FIELD_WARN);
 
356
                             !ignore) ?
 
357
                            CHECK_FIELD_ERROR_FOR_NULL :
 
358
                            CHECK_FIELD_WARN);
327
359
  session->cuted_fields = 0L;
328
360
  table->next_number_field=table->found_next_number_field;
329
361
 
 
362
  if (session->slave_thread &&
 
363
      (info.handle_duplicates == DUP_UPDATE) &&
 
364
      (table->next_number_field != NULL) &&
 
365
      rpl_master_has_bug(&active_mi->rli, 24432))
 
366
    goto abort;
 
367
 
330
368
  error=0;
331
369
  session->set_proc_info("update");
332
370
  if (duplic == DUP_REPLACE)
333
 
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
371
    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
334
372
  if (duplic == DUP_UPDATE)
335
 
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
 
373
    table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
336
374
  {
337
375
    if (duplic != DUP_ERROR || ignore)
338
 
      table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
339
 
    table->cursor->ha_start_bulk_insert(values_list.elements);
 
376
      table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
377
    table->file->ha_start_bulk_insert(values_list.elements);
340
378
  }
341
379
 
342
380
 
348
386
  {
349
387
    if (fields.elements || !value_count)
350
388
    {
351
 
      table->restoreRecordAsDefault();  // Get empty record
352
 
      if (fill_record(session, fields, *values))
 
389
      restore_record(table,s->default_values);  // Get empty record
 
390
      if (fill_record(session, fields, *values, 0))
353
391
      {
354
392
        if (values_list.elements != 1 && ! session->is_error())
355
393
        {
367
405
    }
368
406
    else
369
407
    {
370
 
      table->restoreRecordAsDefault();  // Get empty record
371
 
 
372
 
      if (fill_record(session, table->field, *values))
 
408
      if (session->used_tables)                 // Column used in values()
 
409
        restore_record(table,s->default_values);        // Get empty record
 
410
      else
 
411
      {
 
412
        /*
 
413
          Fix delete marker. No need to restore rest of record since it will
 
414
          be overwritten by fill_record() anyway (and fill_record() does not
 
415
          use default values in this case).
 
416
        */
 
417
        table->record[0][0]= table->s->default_values[0];
 
418
      }
 
419
      if (fill_record(session, table->field, *values, 0))
373
420
      {
374
421
        if (values_list.elements != 1 && ! session->is_error())
375
422
        {
381
428
      }
382
429
    }
383
430
 
384
 
    // Release latches in case bulk insert takes a long time
385
 
    plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
386
 
 
387
431
    error=write_record(session, table ,&info);
388
432
    if (error)
389
433
      break;
402
446
      Do not do this release if this is a delayed insert, it would steal
403
447
      auto_inc values from the delayed_insert thread as they share Table.
404
448
    */
405
 
    table->cursor->ha_release_auto_increment();
406
 
    if (table->cursor->ha_end_bulk_insert() && !error)
 
449
    table->file->ha_release_auto_increment();
 
450
    if (table->file->ha_end_bulk_insert() && !error)
407
451
    {
408
 
      table->print_error(errno,MYF(0));
 
452
      table->file->print_error(my_errno,MYF(0));
409
453
      error=1;
410
454
    }
411
455
    if (duplic != DUP_ERROR || ignore)
412
 
      table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
413
 
 
414
 
    transactional_table= table->cursor->has_transactions();
415
 
 
416
 
    changed= (info.copied || info.deleted || info.updated);
417
 
    if ((changed && error <= 0) || session->transaction.stmt.hasModifiedNonTransData())
418
 
    {
419
 
      if (session->transaction.stmt.hasModifiedNonTransData())
420
 
        session->transaction.all.markModifiedNonTransData();
421
 
    }
422
 
    assert(transactional_table || !changed || session->transaction.stmt.hasModifiedNonTransData());
 
456
      table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
457
 
 
458
    transactional_table= table->file->has_transactions();
 
459
 
 
460
    if ((changed= (info.copied || info.deleted || info.updated)))
 
461
    {
 
462
      /*
 
463
        Invalidate the table in the query cache if something changed.
 
464
        For the transactional algorithm to work the invalidation must be
 
465
        before binlog writing and ha_autocommit_or_rollback
 
466
      */
 
467
    }
 
468
    if ((changed && error <= 0) || session->transaction.stmt.modified_non_trans_table || was_insert_delayed)
 
469
    {
 
470
      if (drizzle_bin_log.is_open())
 
471
      {
 
472
        if (error <= 0)
 
473
        {
 
474
          /*
 
475
            [Guilhem wrote] Temporary errors may have filled
 
476
            session->net.last_error/errno.  For example if there has
 
477
            been a disk full error when writing the row, and it was
 
478
            MyISAM, then session->net.last_error/errno will be set to
 
479
            "disk full"... and the my_pwrite() will wait until free
 
480
            space appears, and so when it finishes then the
 
481
            write_row() was entirely successful
 
482
          */
 
483
          /* todo: consider removing */
 
484
          session->clear_error();
 
485
        }
 
486
        /* bug#22725:
 
487
 
 
488
        A query which per-row-loop can not be interrupted with
 
489
        KILLED, like INSERT, and that does not invoke stored
 
490
        routines can be binlogged with neglecting the KILLED error.
 
491
        
 
492
        If there was no error (error == zero) until after the end of
 
493
        inserting loop the KILLED flag that appeared later can be
 
494
        disregarded since previously possible invocation of stored
 
495
        routines did not result in any error due to the KILLED.  In
 
496
        such case the flag is ignored for constructing binlog event.
 
497
        */
 
498
        assert(session->killed != Session::KILL_BAD_DATA || error > 0);
 
499
        if (session->binlog_query(Session::ROW_QUERY_TYPE,
 
500
                              session->query, session->query_length,
 
501
                              transactional_table, false,
 
502
                              (error>0) ? session->killed : Session::NOT_KILLED) &&
 
503
            transactional_table)
 
504
        {
 
505
          error=1;
 
506
        }
 
507
      }
 
508
      if (session->transaction.stmt.modified_non_trans_table)
 
509
        session->transaction.all.modified_non_trans_table= true;
 
510
    }
 
511
    assert(transactional_table || !changed || 
 
512
                session->transaction.stmt.modified_non_trans_table);
423
513
 
424
514
  }
425
515
  session->set_proc_info("end");
443
533
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
444
534
  table->auto_increment_field_not_null= false;
445
535
  if (duplic == DUP_REPLACE)
446
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
536
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
447
537
 
448
538
  if (error)
449
539
    goto abort;
450
540
  if (values_list.elements == 1 && (!(session->options & OPTION_WARNINGS) ||
451
541
                                    !session->cuted_fields))
452
542
  {
453
 
    session->row_count_func= info.copied + info.deleted + info.updated;
454
 
    session->my_ok((ulong) session->row_count_func,
455
 
                   info.copied + info.deleted + info.touched, id);
 
543
    session->row_count_func= info.copied + info.deleted +
 
544
                         ((session->client_capabilities & CLIENT_FOUND_ROWS) ?
 
545
                          info.touched : info.updated);
 
546
    my_ok(session, (ulong) session->row_count_func, id);
456
547
  }
457
548
  else
458
549
  {
459
550
    char buff[160];
 
551
    ha_rows updated=((session->client_capabilities & CLIENT_FOUND_ROWS) ?
 
552
                     info.touched : info.updated);
460
553
    if (ignore)
461
 
      snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
554
      sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
462
555
              (ulong) (info.records - info.copied), (ulong) session->cuted_fields);
463
556
    else
464
 
      snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
465
 
              (ulong) (info.deleted + info.updated), (ulong) session->cuted_fields);
466
 
    session->row_count_func= info.copied + info.deleted + info.updated;
467
 
    session->my_ok((ulong) session->row_count_func,
468
 
                   info.copied + info.deleted + info.touched, id, buff);
 
557
      sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
 
558
              (ulong) (info.deleted + updated), (ulong) session->cuted_fields);
 
559
    session->row_count_func= info.copied + info.deleted + updated;
 
560
    ::my_ok(session, (ulong) session->row_count_func, id, buff);
469
561
  }
470
562
  session->abort_on_warning= 0;
471
 
  DRIZZLE_INSERT_DONE(0, session->row_count_func);
472
 
  return false;
 
563
  DRIZZLE_INSERT_END();
 
564
  return(false);
473
565
 
474
566
abort:
475
567
  if (table != NULL)
476
 
    table->cursor->ha_release_auto_increment();
 
568
    table->file->ha_release_auto_increment();
477
569
  if (!joins_freed)
478
570
    free_underlaid_joins(session, &session->lex->select_lex);
479
571
  session->abort_on_warning= 0;
480
 
  DRIZZLE_INSERT_DONE(1, 0);
481
 
  return true;
 
572
  DRIZZLE_INSERT_END();
 
573
  return(true);
482
574
}
483
575
 
484
576
 
499
591
*/
500
592
 
501
593
static bool mysql_prepare_insert_check_table(Session *session, TableList *table_list,
502
 
                                             List<Item> &,
 
594
                                             List<Item> &fields __attribute__((unused)),
503
595
                                             bool select_insert)
504
596
{
505
 
 
 
597
  
506
598
 
507
599
  /*
508
600
     first table in list is the one we'll INSERT into, requires INSERT_ACL.
530
622
    session                     Thread handler
531
623
    table_list          Global/local table list
532
624
    table               Table to insert into (can be NULL if table should
533
 
                        be taken from table_list->table)
 
625
                        be taken from table_list->table)    
534
626
    where               Where clause (for insert ... select)
535
627
    select_insert       true if INSERT ... SELECT statement
536
 
    check_fields        true if need to check that all INSERT fields are
 
628
    check_fields        true if need to check that all INSERT fields are 
537
629
                        given values.
538
 
    abort_on_warning    whether to report if some INSERT field is not
 
630
    abort_on_warning    whether to report if some INSERT field is not 
539
631
                        assigned as an error (true) or as a warning (false).
540
632
 
541
633
  TODO (in far future)
547
639
  WARNING
548
640
    You MUST set table->insert_values to 0 after calling this function
549
641
    before releasing the table object.
550
 
 
 
642
  
551
643
  RETURN VALUE
552
644
    false OK
553
645
    true  error
557
649
                          Table *table, List<Item> &fields, List_item *values,
558
650
                          List<Item> &update_fields, List<Item> &update_values,
559
651
                          enum_duplicates duplic,
560
 
                          COND **,
 
652
                          COND **where __attribute__((unused)),
561
653
                          bool select_insert,
562
654
                          bool check_fields, bool abort_on_warning)
563
655
{
564
 
  Select_Lex *select_lex= &session->lex->select_lex;
 
656
  SELECT_LEX *select_lex= &session->lex->select_lex;
565
657
  Name_resolution_context *context= &select_lex->context;
566
658
  Name_resolution_context_state ctx_state;
567
659
  bool insert_into_view= (0 != 0);
568
660
  bool res= 0;
569
661
  table_map map= 0;
570
 
 
 
662
  
571
663
  /* INSERT should have a SELECT or VALUES clause */
572
664
  assert (!select_insert || !values);
573
665
 
574
666
  /*
575
667
    For subqueries in VALUES() we should not see the table in which we are
576
668
    inserting (for INSERT ... SELECT this is done by changing table_list,
577
 
    because INSERT ... SELECT share Select_Lex it with SELECT.
 
669
    because INSERT ... SELECT share SELECT_LEX it with SELECT.
578
670
  */
579
671
  if (!select_insert)
580
672
  {
581
 
    for (Select_Lex_Unit *un= select_lex->first_inner_unit();
 
673
    for (SELECT_LEX_UNIT *un= select_lex->first_inner_unit();
582
674
         un;
583
675
         un= un->next_unit())
584
676
    {
585
 
      for (Select_Lex *sl= un->first_select();
 
677
      for (SELECT_LEX *sl= un->first_select();
586
678
           sl;
587
679
           sl= sl->next_select())
588
680
      {
626
718
    {
627
719
      bool saved_abort_on_warning= session->abort_on_warning;
628
720
      session->abort_on_warning= abort_on_warning;
629
 
      res= check_that_all_fields_are_given_values(session,
630
 
                                                  table ? table :
 
721
      res= check_that_all_fields_are_given_values(session, 
 
722
                                                  table ? table : 
631
723
                                                  context->table_list->table,
632
724
                                                  context->table_list);
633
725
      session->abort_on_warning= saved_abort_on_warning;
654
746
  if (!select_insert)
655
747
  {
656
748
    TableList *duplicate;
657
 
    if ((duplicate= unique_table(table_list, table_list->next_global, true)))
 
749
    if ((duplicate= unique_table(session, table_list, table_list->next_global, 1)))
658
750
    {
659
 
      my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->alias);
660
 
 
661
 
      return true;
 
751
      update_non_unique_table_error(table_list, "INSERT", duplicate);
 
752
      return(true);
662
753
    }
663
754
  }
664
755
  if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
665
756
    table->prepare_for_position();
666
 
 
667
 
  return false;
 
757
  return(false);
668
758
}
669
759
 
670
760
 
697
787
    then both on update triggers will work instead. Similarly both on
698
788
    delete triggers will be invoked if we will delete conflicting records.
699
789
 
700
 
    Sets session->transaction.stmt.modified_non_trans_data to true if table which is updated didn't have
 
790
    Sets session->transaction.stmt.modified_non_trans_table to true if table which is updated didn't have
701
791
    transactions.
702
792
 
703
793
  RETURN VALUE
710
800
{
711
801
  int error;
712
802
  char *key=0;
713
 
  MyBitmap *save_read_set, *save_write_set;
714
 
  uint64_t prev_insert_id= table->cursor->next_insert_id;
 
803
  MY_BITMAP *save_read_set, *save_write_set;
 
804
  uint64_t prev_insert_id= table->file->next_insert_id;
715
805
  uint64_t insert_id_for_cur_row= 0;
716
 
 
 
806
  
717
807
 
718
808
  info->records++;
719
809
  save_read_set=  table->read_set;
720
810
  save_write_set= table->write_set;
721
811
 
722
 
  if (info->handle_duplicates == DUP_REPLACE || info->handle_duplicates == DUP_UPDATE)
 
812
  if (info->handle_duplicates == DUP_REPLACE ||
 
813
      info->handle_duplicates == DUP_UPDATE)
723
814
  {
724
 
    while ((error=table->cursor->ha_write_row(table->record[0])))
 
815
    while ((error=table->file->ha_write_row(table->record[0])))
725
816
    {
726
817
      uint32_t key_nr;
727
818
      /*
731
822
        the autogenerated value to avoid session->insert_id_for_cur_row to become
732
823
        0.
733
824
      */
734
 
      if (table->cursor->insert_id_for_cur_row > 0)
735
 
        insert_id_for_cur_row= table->cursor->insert_id_for_cur_row;
 
825
      if (table->file->insert_id_for_cur_row > 0)
 
826
        insert_id_for_cur_row= table->file->insert_id_for_cur_row;
736
827
      else
737
 
        table->cursor->insert_id_for_cur_row= insert_id_for_cur_row;
 
828
        table->file->insert_id_for_cur_row= insert_id_for_cur_row;
738
829
      bool is_duplicate_key_error;
739
 
      if (table->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
830
      if (table->file->is_fatal_error(error, HA_CHECK_DUP))
740
831
        goto err;
741
 
      is_duplicate_key_error= table->cursor->is_fatal_error(error, 0);
 
832
      is_duplicate_key_error= table->file->is_fatal_error(error, 0);
742
833
      if (!is_duplicate_key_error)
743
834
      {
744
835
        /*
750
841
          goto gok_or_after_err; /* Ignoring a not fatal error, return 0 */
751
842
        goto err;
752
843
      }
753
 
      if ((int) (key_nr = table->get_dup_key(error)) < 0)
 
844
      if ((int) (key_nr = table->file->get_dup_key(error)) < 0)
754
845
      {
755
846
        error= HA_ERR_FOUND_DUPP_KEY;         /* Database can't find key */
756
847
        goto err;
767
858
          key_nr == table->s->next_number_index &&
768
859
          (insert_id_for_cur_row > 0))
769
860
        goto err;
770
 
      if (table->cursor->getEngine()->check_flag(HTON_BIT_DUPLICATE_POS))
 
861
      if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
771
862
      {
772
 
        if (table->cursor->rnd_pos(table->record[1],table->cursor->dup_ref))
 
863
        if (table->file->rnd_pos(table->record[1],table->file->dup_ref))
773
864
          goto err;
774
865
      }
775
866
      else
776
867
      {
777
 
        if (table->cursor->extra(HA_EXTRA_FLUSH_CACHE)) /* Not needed with NISAM */
 
868
        if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) /* Not needed with NISAM */
778
869
        {
779
 
          error=errno;
 
870
          error=my_errno;
780
871
          goto err;
781
872
        }
782
873
 
783
874
        if (!key)
784
875
        {
785
 
          if (!(key=(char*) malloc(table->s->max_unique_length)))
 
876
          if (!(key=(char*) my_safe_alloca(table->s->max_unique_length,
 
877
                                           MAX_KEY_LENGTH)))
786
878
          {
787
879
            error=ENOMEM;
788
880
            goto err;
789
881
          }
790
882
        }
791
883
        key_copy((unsigned char*) key,table->record[0],table->key_info+key_nr,0);
792
 
        if ((error=(table->cursor->index_read_idx_map(table->record[1],key_nr,
 
884
        if ((error=(table->file->index_read_idx_map(table->record[1],key_nr,
793
885
                                                    (unsigned char*) key, HA_WHOLE_KEY,
794
886
                                                    HA_READ_KEY_EXACT))))
795
887
          goto err;
802
894
          an error is returned
803
895
        */
804
896
        assert(table->insert_values != NULL);
805
 
        table->storeRecordAsInsert();
806
 
        table->restoreRecord();
 
897
        store_record(table,insert_values);
 
898
        restore_record(table,record[1]);
807
899
        assert(info->update_fields->elements ==
808
900
                    info->update_values->elements);
809
901
        if (fill_record(session, *info->update_fields,
811
903
                                                 info->ignore))
812
904
          goto before_err;
813
905
 
814
 
        table->cursor->restore_auto_increment(prev_insert_id);
 
906
        table->file->restore_auto_increment(prev_insert_id);
815
907
        if (table->next_number_field)
816
 
          table->cursor->adjust_next_insert_id_after_explicit_value(
 
908
          table->file->adjust_next_insert_id_after_explicit_value(
817
909
            table->next_number_field->val_int());
818
910
        info->touched++;
819
 
        if ((table->cursor->getEngine()->check_flag(HTON_BIT_PARTIAL_COLUMN_READ) &&
 
911
        if ((table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ &&
820
912
             !bitmap_is_subset(table->write_set, table->read_set)) ||
821
913
            table->compare_record())
822
914
        {
823
 
          if ((error=table->cursor->ha_update_row(table->record[1],
 
915
          if ((error=table->file->ha_update_row(table->record[1],
824
916
                                                table->record[0])) &&
825
917
              error != HA_ERR_RECORD_IS_THE_SAME)
826
918
          {
827
919
            if (info->ignore &&
828
 
                !table->cursor->is_fatal_error(error, HA_CHECK_DUP_KEY))
 
920
                !table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
829
921
            {
830
922
              goto gok_or_after_err;
831
923
            }
843
935
            Except if LAST_INSERT_ID(#) was in the INSERT query, which is
844
936
            handled separately by Session::arg_of_last_insert_id_function.
845
937
          */
846
 
          insert_id_for_cur_row= table->cursor->insert_id_for_cur_row= 0;
 
938
          insert_id_for_cur_row= table->file->insert_id_for_cur_row= 0;
847
939
          info->copied++;
848
940
        }
849
941
 
850
942
        if (table->next_number_field)
851
 
          table->cursor->adjust_next_insert_id_after_explicit_value(
 
943
          table->file->adjust_next_insert_id_after_explicit_value(
852
944
            table->next_number_field->val_int());
853
945
        info->touched++;
854
946
 
861
953
          an INSERT or DELETE(s) + INSERT; FOREIGN KEY checks in
862
954
          InnoDB do not function in the defined way if we allow MySQL
863
955
          to convert the latter operation internally to an UPDATE.
864
 
          We also should not perform this conversion if we have
 
956
          We also should not perform this conversion if we have 
865
957
          timestamp field with ON UPDATE which is different from DEFAULT.
866
958
          Another case when conversion should not be performed is when
867
959
          we have ON DELETE trigger on table so user may notice that
871
963
          ON UPDATE triggers.
872
964
        */
873
965
        if (last_uniq_key(table,key_nr) &&
874
 
            !table->cursor->referenced_by_foreign_key() &&
 
966
            !table->file->referenced_by_foreign_key() &&
875
967
            (table->timestamp_field_type == TIMESTAMP_NO_AUTO_SET ||
876
968
             table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH))
877
969
        {
878
 
          if ((error=table->cursor->ha_update_row(table->record[1],
 
970
          if ((error=table->file->ha_update_row(table->record[1],
879
971
                                                table->record[0])) &&
880
972
              error != HA_ERR_RECORD_IS_THE_SAME)
881
973
            goto err;
883
975
            info->deleted++;
884
976
          else
885
977
            error= 0;
886
 
          session->record_first_successful_insert_id_in_cur_stmt(table->cursor->insert_id_for_cur_row);
 
978
          session->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
887
979
          /*
888
980
            Since we pretend that we have done insert we should call
889
981
            its after triggers.
892
984
        }
893
985
        else
894
986
        {
895
 
          if ((error=table->cursor->ha_delete_row(table->record[1])))
 
987
          if ((error=table->file->ha_delete_row(table->record[1])))
896
988
            goto err;
897
989
          info->deleted++;
898
 
          if (!table->cursor->has_transactions())
899
 
            session->transaction.stmt.markModifiedNonTransData();
 
990
          if (!table->file->has_transactions())
 
991
            session->transaction.stmt.modified_non_trans_table= true;
900
992
          /* Let us attempt do write_row() once more */
901
993
        }
902
994
      }
903
995
    }
904
 
    session->record_first_successful_insert_id_in_cur_stmt(table->cursor->insert_id_for_cur_row);
 
996
    session->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
905
997
    /*
906
998
      Restore column maps if they where replaced during an duplicate key
907
999
      problem.
910
1002
        table->write_set != save_write_set)
911
1003
      table->column_bitmaps_set(save_read_set, save_write_set);
912
1004
  }
913
 
  else if ((error=table->cursor->ha_write_row(table->record[0])))
 
1005
  else if ((error=table->file->ha_write_row(table->record[0])))
914
1006
  {
915
1007
    if (!info->ignore ||
916
 
        table->cursor->is_fatal_error(error, HA_CHECK_DUP))
 
1008
        table->file->is_fatal_error(error, HA_CHECK_DUP))
917
1009
      goto err;
918
 
    table->cursor->restore_auto_increment(prev_insert_id);
 
1010
    table->file->restore_auto_increment(prev_insert_id);
919
1011
    goto gok_or_after_err;
920
1012
  }
921
1013
 
922
1014
after_n_copied_inc:
923
1015
  info->copied++;
924
 
  session->record_first_successful_insert_id_in_cur_stmt(table->cursor->insert_id_for_cur_row);
 
1016
  session->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
925
1017
 
926
1018
gok_or_after_err:
927
1019
  if (key)
928
 
    free(key);
929
 
  if (!table->cursor->has_transactions())
930
 
    session->transaction.stmt.markModifiedNonTransData();
 
1020
    my_safe_afree(key,table->s->max_unique_length,MAX_KEY_LENGTH);
 
1021
  if (!table->file->has_transactions())
 
1022
    session->transaction.stmt.modified_non_trans_table= true;
931
1023
  return(0);
932
1024
 
933
1025
err:
935
1027
  /* current_select is NULL if this is a delayed insert */
936
1028
  if (session->lex->current_select)
937
1029
    session->lex->current_select->no_error= 0;        // Give error
938
 
  table->print_error(error,MYF(0));
939
 
 
 
1030
  table->file->print_error(error,MYF(0));
 
1031
  
940
1032
before_err:
941
 
  table->cursor->restore_auto_increment(prev_insert_id);
 
1033
  table->file->restore_auto_increment(prev_insert_id);
942
1034
  if (key)
943
 
    free(key);
 
1035
    my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH);
944
1036
  table->column_bitmaps_set(save_read_set, save_write_set);
945
1037
  return(1);
946
1038
}
951
1043
******************************************************************************/
952
1044
 
953
1045
int check_that_all_fields_are_given_values(Session *session, Table *entry,
954
 
                                           TableList *)
 
1046
                                           TableList *table_list)
955
1047
{
956
1048
  int err= 0;
 
1049
  MY_BITMAP *write_set= entry->write_set;
957
1050
 
958
1051
  for (Field **field=entry->field ; *field ; field++)
959
1052
  {
960
 
    if (((*field)->isWriteSet()) == false)
961
 
    {
962
 
      /*
963
 
       * If the field doesn't have any default value
964
 
       * and there is no actual value specified in the
965
 
       * INSERT statement, throw error ER_NO_DEFAULT_FOR_FIELD.
966
 
       */
967
 
      if (((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
 
1053
    if (!bitmap_is_set(write_set, (*field)->field_index) &&
 
1054
        ((*field)->flags & NO_DEFAULT_VALUE_FLAG) &&
968
1055
        ((*field)->real_type() != DRIZZLE_TYPE_ENUM))
969
 
      {
970
 
        my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), (*field)->field_name);
971
 
        err= 1;
972
 
      }
973
 
    }
974
 
    else
975
1056
    {
976
 
      /*
977
 
       * However, if an actual NULL value was specified
978
 
       * for the field and the field is a NOT NULL field, 
979
 
       * throw ER_BAD_NULL_ERROR.
980
 
       *
981
 
       * Per the SQL standard, inserting NULL into a NOT NULL
982
 
       * field requires an error to be thrown.
983
 
       */
984
 
      if (((*field)->flags & NOT_NULL_FLAG) &&
985
 
          (*field)->is_null())
986
 
      {
987
 
        my_error(ER_BAD_NULL_ERROR, MYF(0), (*field)->field_name);
988
 
        err= 1;
989
 
      }
 
1057
      bool view= false;
 
1058
      if (table_list)
 
1059
      {
 
1060
        table_list= table_list->top_table();
 
1061
        view= test(0);
 
1062
      }
 
1063
      {
 
1064
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
 
1065
                            ER_NO_DEFAULT_FOR_FIELD,
 
1066
                            ER(ER_NO_DEFAULT_FOR_FIELD),
 
1067
                            (*field)->field_name);
 
1068
      }
 
1069
      err= 1;
990
1070
    }
991
1071
  }
992
1072
  return session->abort_on_warning ? err : 0;
1012
1092
bool mysql_insert_select_prepare(Session *session)
1013
1093
{
1014
1094
  LEX *lex= session->lex;
1015
 
  Select_Lex *select_lex= &lex->select_lex;
1016
 
 
 
1095
  SELECT_LEX *select_lex= &lex->select_lex;
 
1096
  
1017
1097
  /*
1018
 
    Select_Lex do not belong to INSERT statement, so we can't add WHERE
 
1098
    SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
1019
1099
    clause if table is VIEW
1020
1100
  */
1021
 
 
 
1101
  
1022
1102
  if (mysql_prepare_insert(session, lex->query_tables,
1023
1103
                           lex->query_tables->table, lex->field_list, 0,
1024
1104
                           lex->update_list, lex->value_list,
1057
1137
 
1058
1138
 
1059
1139
int
1060
 
select_insert::prepare(List<Item> &values, Select_Lex_Unit *u)
 
1140
select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
1061
1141
{
1062
1142
  LEX *lex= session->lex;
1063
1143
  int res;
1064
1144
  table_map map= 0;
1065
 
  Select_Lex *lex_current_select_save= lex->current_select;
1066
 
 
 
1145
  SELECT_LEX *lex_current_select_save= lex->current_select;
 
1146
  
1067
1147
 
1068
1148
  unit= u;
1069
1149
 
1081
1161
  {
1082
1162
    bool saved_abort_on_warning= session->abort_on_warning;
1083
1163
    session->abort_on_warning= !info.ignore;
1084
 
    res= check_that_all_fields_are_given_values(session, table_list->table,
 
1164
    res= check_that_all_fields_are_given_values(session, table_list->table, 
1085
1165
                                                table_list);
1086
1166
    session->abort_on_warning= saved_abort_on_warning;
1087
1167
  }
1101
1181
    res= res || check_update_fields(session, context->table_list,
1102
1182
                                    *info.update_fields, &map);
1103
1183
    /*
1104
 
      When we are not using GROUP BY and there are no ungrouped aggregate functions
 
1184
      When we are not using GROUP BY and there are no ungrouped aggregate functions 
1105
1185
      we can refer to other tables in the ON DUPLICATE KEY part.
1106
1186
      We use next_name_resolution_table descructively, so check it first (views?)
1107
1187
    */
1112
1192
        We must make a single context out of the two separate name resolution contexts :
1113
1193
        the INSERT table and the tables in the SELECT part of INSERT ... SELECT.
1114
1194
        To do that we must concatenate the two lists
1115
 
      */
1116
 
      table_list->next_name_resolution_table=
 
1195
      */  
 
1196
      table_list->next_name_resolution_table= 
1117
1197
        ctx_state.get_first_name_resolution_table();
1118
1198
 
1119
1199
    res= res || setup_fields(session, 0, *info.update_values,
1153
1233
    Is table which we are changing used somewhere in other parts of
1154
1234
    query
1155
1235
  */
1156
 
  if (unique_table(table_list, table_list->next_global))
 
1236
  if (unique_table(session, table_list, table_list->next_global, 0))
1157
1237
  {
1158
1238
    /* Using same table for INSERT and SELECT */
1159
1239
    lex->current_select->options|= OPTION_BUFFER_RESULT;
1162
1242
  else if (!(lex->current_select->options & OPTION_BUFFER_RESULT))
1163
1243
  {
1164
1244
    /*
1165
 
      We must not yet prepare the result table if it is the same as one of the
1166
 
      source tables (INSERT SELECT). The preparation may disable
 
1245
      We must not yet prepare the result table if it is the same as one of the 
 
1246
      source tables (INSERT SELECT). The preparation may disable 
1167
1247
      indexes on the result table, which may be used during the select, if it
1168
1248
      is the same table (Bug #6034). Do the preparation after the select phase
1169
1249
      in select_insert::prepare2().
1170
1250
      We won't start bulk inserts at all if this statement uses functions or
1171
1251
      should invoke triggers since they may access to the same table too.
1172
1252
    */
1173
 
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
1253
    table->file->ha_start_bulk_insert((ha_rows) 0);
1174
1254
  }
1175
 
  table->restoreRecordAsDefault();              // Get empty record
 
1255
  restore_record(table,s->default_values);              // Get empty record
1176
1256
  table->next_number_field=table->found_next_number_field;
1177
1257
 
 
1258
  if (session->slave_thread &&
 
1259
      (info.handle_duplicates == DUP_UPDATE) &&
 
1260
      (table->next_number_field != NULL) &&
 
1261
      rpl_master_has_bug(&active_mi->rli, 24432))
 
1262
    return(1);
 
1263
 
1178
1264
  session->cuted_fields=0;
1179
1265
  if (info.ignore || info.handle_duplicates != DUP_ERROR)
1180
 
    table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1266
    table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1181
1267
  if (info.handle_duplicates == DUP_REPLACE)
1182
 
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
1268
    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
1183
1269
  if (info.handle_duplicates == DUP_UPDATE)
1184
 
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
 
1270
    table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
1185
1271
  session->abort_on_warning= !info.ignore;
1186
1272
  table->mark_columns_needed_for_insert();
1187
1273
 
1201
1287
    If the result table is the same as one of the source tables (INSERT SELECT),
1202
1288
    the result table is not finally prepared at the join prepair phase.
1203
1289
    Do the final preparation now.
1204
 
 
 
1290
                       
1205
1291
  RETURN
1206
1292
    0   OK
1207
1293
*/
1208
1294
 
1209
1295
int select_insert::prepare2(void)
1210
1296
{
1211
 
 
 
1297
  
1212
1298
  if (session->lex->current_select->options & OPTION_BUFFER_RESULT)
1213
 
    table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
1299
    table->file->ha_start_bulk_insert((ha_rows) 0);
1214
1300
  return(0);
1215
1301
}
1216
1302
 
1223
1309
 
1224
1310
select_insert::~select_insert()
1225
1311
{
1226
 
 
 
1312
  
1227
1313
  if (table)
1228
1314
  {
1229
1315
    table->next_number_field=0;
1230
1316
    table->auto_increment_field_not_null= false;
1231
 
    table->cursor->ha_reset();
 
1317
    table->file->ha_reset();
1232
1318
  }
1233
1319
  session->count_cuted_fields= CHECK_FIELD_IGNORE;
1234
1320
  session->abort_on_warning= 0;
1238
1324
 
1239
1325
bool select_insert::send_data(List<Item> &values)
1240
1326
{
1241
 
 
 
1327
  
1242
1328
  bool error=0;
1243
1329
 
1244
1330
  if (unit->offset_limit_cnt)
1253
1339
  if (session->is_error())
1254
1340
    return(1);
1255
1341
 
1256
 
  // Release latches in case bulk insert takes a long time
1257
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(session);
1258
 
 
1259
1342
  error= write_record(session, table, &info);
1260
 
 
 
1343
    
1261
1344
  if (!error)
1262
1345
  {
1263
1346
    if (info.handle_duplicates == DUP_UPDATE)
1265
1348
      /*
1266
1349
        Restore fields of the record since it is possible that they were
1267
1350
        changed by ON DUPLICATE KEY UPDATE clause.
1268
 
 
 
1351
    
1269
1352
        If triggers exist then whey can modify some fields which were not
1270
1353
        originally touched by INSERT ... SELECT, so we have to restore
1271
1354
        their original values for the next row.
1272
1355
      */
1273
 
      table->restoreRecordAsDefault();
 
1356
      restore_record(table, s->default_values);
1274
1357
    }
1275
1358
    if (table->next_number_field)
1276
1359
    {
1279
1362
        value we just saw, we may need to send it to client in the end.
1280
1363
      */
1281
1364
      if (session->first_successful_insert_id_in_cur_stmt == 0) // optimization
1282
 
        autoinc_value_of_last_inserted_row=
 
1365
        autoinc_value_of_last_inserted_row= 
1283
1366
          table->next_number_field->val_int();
1284
1367
      /*
1285
1368
        Clear auto-increment field for the next record, if triggers are used
1295
1378
void select_insert::store_values(List<Item> &values)
1296
1379
{
1297
1380
  if (fields->elements)
1298
 
    fill_record(session, *fields, values, true);
 
1381
    fill_record(session, *fields, values, 1);
1299
1382
  else
1300
 
    fill_record(session, table->field, values, true);
 
1383
    fill_record(session, table->field, values, 1);
1301
1384
}
1302
1385
 
1303
1386
void select_insert::send_error(uint32_t errcode,const char *err)
1304
1387
{
1305
 
 
 
1388
  
1306
1389
 
1307
1390
  my_message(errcode, err, MYF(0));
1308
1391
 
1313
1396
bool select_insert::send_eof()
1314
1397
{
1315
1398
  int error;
1316
 
  bool const trans_table= table->cursor->has_transactions();
 
1399
  bool const trans_table= table->file->has_transactions();
1317
1400
  uint64_t id;
1318
1401
  bool changed;
1319
 
 
1320
 
  error= table->cursor->ha_end_bulk_insert();
1321
 
  table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1322
 
  table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
1402
  Session::killed_state killed_status= session->killed;
 
1403
  
 
1404
  error= table->file->ha_end_bulk_insert();
 
1405
  table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1406
  table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1323
1407
 
1324
1408
  if ((changed= (info.copied || info.deleted || info.updated)))
1325
1409
  {
1326
1410
    /*
1327
1411
      We must invalidate the table in the query cache before binlog writing
1328
 
      and autocommitOrRollback.
 
1412
      and ha_autocommit_or_rollback.
1329
1413
    */
1330
 
    if (session->transaction.stmt.hasModifiedNonTransData())
1331
 
      session->transaction.all.markModifiedNonTransData();
 
1414
    if (session->transaction.stmt.modified_non_trans_table)
 
1415
      session->transaction.all.modified_non_trans_table= true;
1332
1416
  }
1333
 
  assert(trans_table || !changed ||
1334
 
              session->transaction.stmt.hasModifiedNonTransData());
 
1417
  assert(trans_table || !changed || 
 
1418
              session->transaction.stmt.modified_non_trans_table);
1335
1419
 
1336
 
  table->cursor->ha_release_auto_increment();
 
1420
  /*
 
1421
    Write to binlog before commiting transaction.  No statement will
 
1422
    be written by the binlog_query() below in RBR mode.  All the
 
1423
    events are in the transaction cache and will be written when
 
1424
    ha_autocommit_or_rollback() is issued below.
 
1425
  */
 
1426
  if (drizzle_bin_log.is_open())
 
1427
  {
 
1428
    if (!error)
 
1429
      session->clear_error();
 
1430
    session->binlog_query(Session::ROW_QUERY_TYPE,
 
1431
                      session->query, session->query_length,
 
1432
                      trans_table, false, killed_status);
 
1433
  }
 
1434
  table->file->ha_release_auto_increment();
1337
1435
 
1338
1436
  if (error)
1339
1437
  {
1340
 
    table->print_error(error,MYF(0));
1341
 
    DRIZZLE_INSERT_SELECT_DONE(error, 0);
1342
 
    return 1;
 
1438
    table->file->print_error(error,MYF(0));
 
1439
    return(1);
1343
1440
  }
1344
1441
  char buff[160];
1345
1442
  if (info.ignore)
1346
 
    snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
1443
    sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
1347
1444
            (ulong) (info.records - info.copied), (ulong) session->cuted_fields);
1348
1445
  else
1349
 
    snprintf(buff, sizeof(buff), ER(ER_INSERT_INFO), (ulong) info.records,
 
1446
    sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
1350
1447
            (ulong) (info.deleted+info.updated), (ulong) session->cuted_fields);
1351
 
  session->row_count_func= info.copied + info.deleted + info.updated;
 
1448
  session->row_count_func= info.copied + info.deleted +
 
1449
                       ((session->client_capabilities & CLIENT_FOUND_ROWS) ?
 
1450
                        info.touched : info.updated);
1352
1451
 
1353
1452
  id= (session->first_successful_insert_id_in_cur_stmt > 0) ?
1354
1453
    session->first_successful_insert_id_in_cur_stmt :
1355
1454
    (session->arg_of_last_insert_id_function ?
1356
1455
     session->first_successful_insert_id_in_prev_stmt :
1357
1456
     (info.copied ? autoinc_value_of_last_inserted_row : 0));
1358
 
  session->my_ok((ulong) session->row_count_func,
1359
 
                 info.copied + info.deleted + info.touched, id, buff);
1360
 
  DRIZZLE_INSERT_SELECT_DONE(0, session->row_count_func);
1361
 
  return 0;
 
1457
  ::my_ok(session, (ulong) session->row_count_func, id, buff);
 
1458
  return(0);
1362
1459
}
1363
1460
 
1364
1461
void select_insert::abort() {
1365
1462
 
1366
 
 
 
1463
  
1367
1464
  /*
1368
1465
    If the creation of the table failed (due to a syntax error, for
1369
1466
    example), no table will have been opened and therefore 'table'
1374
1471
  {
1375
1472
    bool changed, transactional_table;
1376
1473
 
1377
 
    table->cursor->ha_end_bulk_insert();
 
1474
    table->file->ha_end_bulk_insert();
1378
1475
 
1379
1476
    /*
1380
1477
      If at least one row has been inserted/modified and will stay in
1391
1488
      zero, so no check for that is made.
1392
1489
    */
1393
1490
    changed= (info.copied || info.deleted || info.updated);
1394
 
    transactional_table= table->cursor->has_transactions();
 
1491
    transactional_table= table->file->has_transactions();
 
1492
    if (session->transaction.stmt.modified_non_trans_table)
 
1493
    {
 
1494
        if (drizzle_bin_log.is_open())
 
1495
          session->binlog_query(Session::ROW_QUERY_TYPE, session->query, session->query_length,
 
1496
                            transactional_table, false);
 
1497
    }
1395
1498
    assert(transactional_table || !changed ||
1396
 
                session->transaction.stmt.hasModifiedNonTransData());
1397
 
    table->cursor->ha_release_auto_increment();
1398
 
  }
1399
 
 
1400
 
  if (DRIZZLE_INSERT_SELECT_DONE_ENABLED())
1401
 
  {
1402
 
    DRIZZLE_INSERT_SELECT_DONE(0, info.copied + info.deleted + info.updated);
 
1499
                session->transaction.stmt.modified_non_trans_table);
 
1500
    table->file->ha_release_auto_increment();
1403
1501
  }
1404
1502
 
1405
1503
  return;
1436
1534
  NOTES
1437
1535
    This function behaves differently for base and temporary tables:
1438
1536
    - For base table we assume that either table exists and was pre-opened
1439
 
      and locked at openTablesLock() stage (and in this case we just
 
1537
      and locked at open_and_lock_tables() stage (and in this case we just
1440
1538
      emit error or warning and return pre-opened Table object) or special
1441
1539
      placeholder was put in table cache that guarantees that this table
1442
1540
      won't be created or opened until the placeholder will be removed
1454
1552
 
1455
1553
static Table *create_table_from_items(Session *session, HA_CREATE_INFO *create_info,
1456
1554
                                      TableList *create_table,
1457
 
                                      message::Table &table_proto,
1458
 
                                      AlterInfo *alter_info,
 
1555
                                      Alter_info *alter_info,
1459
1556
                                      List<Item> *items,
1460
 
                                      bool is_if_not_exists,
1461
1557
                                      DRIZZLE_LOCK **lock,
1462
 
                                      TableIdentifier &identifier)
 
1558
                                      Tableop_hooks *hooks)
1463
1559
{
1464
 
  Table tmp_table;              // Used during 'CreateField()'
1465
 
  TableShare share;
 
1560
  Table tmp_table;              // Used during 'Create_field()'
 
1561
  TABLE_SHARE share;
1466
1562
  Table *table= 0;
1467
1563
  uint32_t select_field_count= items->elements;
1468
1564
  /* Add selected items to field list */
1471
1567
  Field *tmp_field;
1472
1568
  bool not_used;
1473
1569
 
1474
 
  if (not (identifier.isTmp()) && create_table->table->db_stat)
 
1570
  if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
 
1571
      create_table->table->db_stat)
1475
1572
  {
1476
 
    /* Table already exists and was open at openTablesLock() stage. */
1477
 
    if (is_if_not_exists)
 
1573
    /* Table already exists and was open at open_and_lock_tables() stage. */
 
1574
    if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1478
1575
    {
1479
1576
      create_info->table_existed= 1;            // Mark that table existed
1480
1577
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1481
1578
                          ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1482
1579
                          create_table->table_name);
1483
 
      return create_table->table;
 
1580
      return(create_table->table);
1484
1581
    }
1485
1582
 
1486
1583
    my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
1487
 
    return NULL;
 
1584
    return(0);
1488
1585
  }
1489
1586
 
1490
1587
  tmp_table.alias= 0;
1491
1588
  tmp_table.timestamp_field= 0;
1492
1589
  tmp_table.s= &share;
 
1590
  init_tmp_table_share(session, &share, "", 0, "", "");
1493
1591
 
1494
1592
  tmp_table.s->db_create_options=0;
1495
1593
  tmp_table.s->blob_ptr_size= portable_sizeof_char_ptr;
1496
 
 
1497
 
  if (not table_proto.engine().name().compare("MyISAM"))
1498
 
    tmp_table.s->db_low_byte_first= true;
1499
 
  else if (not table_proto.engine().name().compare("MEMORY"))
1500
 
    tmp_table.s->db_low_byte_first= true;
1501
 
 
 
1594
  tmp_table.s->db_low_byte_first= 
 
1595
        test(create_info->db_type == myisam_hton ||
 
1596
             create_info->db_type == heap_hton);
1502
1597
  tmp_table.null_row= false;
1503
1598
  tmp_table.maybe_null= false;
1504
1599
 
1505
1600
  while ((item=it++))
1506
1601
  {
1507
 
    CreateField *cr_field;
 
1602
    Create_field *cr_field;
1508
1603
    Field *field, *def_field;
1509
1604
    if (item->type() == Item::FUNC_ITEM)
1510
1605
      if (item->result_type() != STRING_RESULT)
1513
1608
        field= item->tmp_table_field_from_field_type(&tmp_table, 0);
1514
1609
    else
1515
1610
      field= create_tmp_field(session, &tmp_table, item, item->type(),
1516
 
                              (Item ***) 0, &tmp_field, &def_field, false,
1517
 
                              false, false, 0);
 
1611
                              (Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
 
1612
                              0);
1518
1613
    if (!field ||
1519
 
        !(cr_field=new CreateField(field,(item->type() == Item::FIELD_ITEM ?
 
1614
        !(cr_field=new Create_field(field,(item->type() == Item::FIELD_ITEM ?
1520
1615
                                           ((Item_field *)item)->field :
1521
1616
                                           (Field*) 0))))
1522
 
      return NULL;
 
1617
      return(0);
1523
1618
    if (item->maybe_null)
1524
1619
      cr_field->flags &= ~NOT_NULL_FLAG;
1525
1620
    alter_info->create_list.push_back(cr_field);
1531
1626
    Note that we either creating (or opening existing) temporary table or
1532
1627
    creating base table on which name we have exclusive lock. So code below
1533
1628
    should not cause deadlocks or races.
 
1629
 
 
1630
    We don't log the statement, it will be logged later.
 
1631
 
 
1632
    If this is a HEAP table, the automatic DELETE FROM which is written to the
 
1633
    binlog when a HEAP table is opened for the first time since startup, must
 
1634
    not be written: 1) it would be wrong (imagine we're in CREATE SELECT: we
 
1635
    don't want to delete from it) 2) it would be written before the CREATE
 
1636
    Table, which is a wrong order. So we keep binary logging disabled when we
 
1637
    open_table().
1534
1638
  */
1535
1639
  {
1536
 
    if (not mysql_create_table_no_lock(session,
1537
 
                                       identifier,
1538
 
                                       create_info,
1539
 
                                       table_proto,
1540
 
                                       alter_info,
1541
 
                                       false,
1542
 
                                       select_field_count,
1543
 
                                       is_if_not_exists))
 
1640
    tmp_disable_binlog(session);
 
1641
    if (!mysql_create_table_no_lock(session, create_table->db,
 
1642
                                    create_table->table_name,
 
1643
                                    create_info, alter_info, 0,
 
1644
                                    select_field_count, true))
1544
1645
    {
1545
 
      if (create_info->table_existed && not identifier.isTmp())
 
1646
      if (create_info->table_existed &&
 
1647
          !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1546
1648
      {
1547
1649
        /*
1548
1650
          This means that someone created table underneath server
1550
1652
          cluster. We don't have much options but throw an error.
1551
1653
        */
1552
1654
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name);
1553
 
        return NULL;
 
1655
        return(0);
1554
1656
      }
1555
1657
 
1556
 
      if (not identifier.isTmp())
 
1658
      if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1557
1659
      {
1558
 
        pthread_mutex_lock(&LOCK_open); /* CREATE TABLE... has found that the table already exists for insert and is adapting to use it */
1559
 
        if (session->reopen_name_locked_table(create_table, false))
 
1660
        pthread_mutex_lock(&LOCK_open);
 
1661
        if (reopen_name_locked_table(session, create_table, false))
1560
1662
        {
1561
 
          quick_rm_table(*session, identifier);
 
1663
          quick_rm_table(create_info->db_type, create_table->db,
 
1664
                         table_case_name(create_info, create_table->table_name),
 
1665
                         0);
1562
1666
        }
1563
1667
        else
1564
1668
          table= create_table->table;
1566
1670
      }
1567
1671
      else
1568
1672
      {
1569
 
        if (not (table= session->openTable(create_table, (bool*) 0,
1570
 
                                           DRIZZLE_OPEN_TEMPORARY_ONLY)) &&
1571
 
            not create_info->table_existed)
 
1673
        if (!(table= open_table(session, create_table, (bool*) 0,
 
1674
                                DRIZZLE_OPEN_TEMPORARY_ONLY)) &&
 
1675
            !create_info->table_existed)
1572
1676
        {
1573
1677
          /*
1574
1678
            This shouldn't happen as creation of temporary table should make
1575
1679
            it preparable for open. But let us do close_temporary_table() here
1576
1680
            just in case.
1577
1681
          */
1578
 
          session->drop_temporary_table(create_table);
 
1682
          drop_temporary_table(session, create_table);
1579
1683
        }
1580
1684
      }
1581
1685
    }
 
1686
    reenable_binlog(session);
1582
1687
    if (!table)                                   // open failed
1583
 
      return NULL;
 
1688
      return(0);
1584
1689
  }
1585
1690
 
1586
1691
  table->reginfo.lock_type=TL_WRITE;
 
1692
  hooks->prelock(&table, 1);                    // Call prelock hooks
1587
1693
  if (! ((*lock)= mysql_lock_tables(session, &table, 1,
1588
 
                                    DRIZZLE_LOCK_IGNORE_FLUSH, &not_used)))
 
1694
                                    DRIZZLE_LOCK_IGNORE_FLUSH, &not_used)) ||
 
1695
        hooks->postlock(&table, 1))
1589
1696
  {
1590
1697
    if (*lock)
1591
1698
    {
1593
1700
      *lock= 0;
1594
1701
    }
1595
1702
 
1596
 
    if (not create_info->table_existed)
1597
 
      session->drop_open_table(table, identifier);
1598
 
    return NULL;
 
1703
    if (!create_info->table_existed)
 
1704
      drop_open_table(session, table, create_table->db, create_table->table_name);
 
1705
    return(0);
1599
1706
  }
1600
 
 
1601
 
  return table;
 
1707
  return(table);
1602
1708
}
1603
1709
 
1604
1710
 
1605
1711
int
1606
 
select_create::prepare(List<Item> &values, Select_Lex_Unit *u)
 
1712
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
1607
1713
{
1608
1714
  DRIZZLE_LOCK *extra_lock= NULL;
 
1715
  
 
1716
 
 
1717
  Tableop_hooks *hook_ptr= NULL;
1609
1718
  /*
1610
 
    For replication, the CREATE-SELECT statement is written
1611
 
    in two pieces: the first transaction messsage contains 
1612
 
    the CREATE TABLE statement as a CreateTableStatement message
1613
 
    necessary to create the table.
1614
 
    
1615
 
    The second transaction message contains all the InsertStatement
1616
 
    and associated InsertRecords that should go into the table.
 
1719
    For row-based replication, the CREATE-SELECT statement is written
 
1720
    in two pieces: the first one contain the CREATE TABLE statement
 
1721
    necessary to create the table and the second part contain the rows
 
1722
    that should go into the table.
 
1723
 
 
1724
    For non-temporary tables, the start of the CREATE-SELECT
 
1725
    implicitly commits the previous transaction, and all events
 
1726
    forming the statement will be stored the transaction cache. At end
 
1727
    of the statement, the entire statement is committed as a
 
1728
    transaction, and all events are written to the binary log.
 
1729
 
 
1730
    On the master, the table is locked for the duration of the
 
1731
    statement, but since the CREATE part is replicated as a simple
 
1732
    statement, there is no way to lock the table for accesses on the
 
1733
    slave.  Hence, we have to hold on to the CREATE part of the
 
1734
    statement until the statement has finished.
1617
1735
   */
 
1736
  class MY_HOOKS : public Tableop_hooks {
 
1737
  public:
 
1738
    MY_HOOKS(select_create *x, TableList *create_table,
 
1739
             TableList *select_tables)
 
1740
      : ptr(x), all_tables(*create_table)
 
1741
      {
 
1742
        all_tables.next_global= select_tables;
 
1743
      }
 
1744
 
 
1745
  private:
 
1746
    virtual int do_postlock(Table **tables, uint32_t count)
 
1747
    {
 
1748
      Table const *const table = *tables;
 
1749
      if (drizzle_bin_log.is_open()
 
1750
          && !table->s->tmp_table 
 
1751
          && !ptr->get_create_info()->table_existed)
 
1752
      {
 
1753
        ptr->binlog_show_create_table(tables, count);
 
1754
      }
 
1755
      return 0;
 
1756
    }
 
1757
 
 
1758
    select_create *ptr;
 
1759
    TableList all_tables;
 
1760
  };
 
1761
 
 
1762
  MY_HOOKS hooks(this, create_table, select_tables);
 
1763
  hook_ptr= &hooks;
1618
1764
 
1619
1765
  unit= u;
1620
1766
 
1621
 
  if (not (table= create_table_from_items(session, create_info, create_table,
1622
 
                                          table_proto,
1623
 
                                          alter_info, &values,
1624
 
                                          is_if_not_exists,
1625
 
                                          &extra_lock, identifier)))
 
1767
  /*
 
1768
    Start a statement transaction before the create if we are using
 
1769
    row-based replication for the statement.  If we are creating a
 
1770
    temporary table, we need to start a statement transaction.
 
1771
  */
 
1772
  if ((session->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) == 0 
 
1773
      && drizzle_bin_log.is_open())
 
1774
  {
 
1775
    session->binlog_start_trans_and_stmt();
 
1776
  }
 
1777
 
 
1778
  if (!(table= create_table_from_items(session, create_info, create_table,
 
1779
                                       alter_info, &values,
 
1780
                                       &extra_lock, hook_ptr)))
1626
1781
    return(-1);                         // abort() deletes table
1627
1782
 
1628
1783
  if (extra_lock)
1629
1784
  {
1630
1785
    assert(m_plock == NULL);
1631
1786
 
1632
 
    if (identifier.isTmp())
 
1787
    if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1633
1788
      m_plock= &m_lock;
1634
1789
    else
1635
1790
      m_plock= &session->extra_lock;
1648
1803
 
1649
1804
  /* Mark all fields that are given values */
1650
1805
  for (Field **f= field ; *f ; f++)
1651
 
    table->setWriteSet((*f)->field_index);
 
1806
    bitmap_set_bit(table->write_set, (*f)->field_index);
1652
1807
 
1653
1808
  /* Don't set timestamp if used */
1654
1809
  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
1655
1810
  table->next_number_field=table->found_next_number_field;
1656
1811
 
1657
 
  table->restoreRecordAsDefault();      // Get empty record
 
1812
  restore_record(table,s->default_values);      // Get empty record
1658
1813
  session->cuted_fields=0;
1659
1814
  if (info.ignore || info.handle_duplicates != DUP_ERROR)
1660
 
    table->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
 
1815
    table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
1661
1816
  if (info.handle_duplicates == DUP_REPLACE)
1662
 
    table->cursor->extra(HA_EXTRA_WRITE_CAN_REPLACE);
 
1817
    table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
1663
1818
  if (info.handle_duplicates == DUP_UPDATE)
1664
 
    table->cursor->extra(HA_EXTRA_INSERT_WITH_UPDATE);
1665
 
  table->cursor->ha_start_bulk_insert((ha_rows) 0);
 
1819
    table->file->extra(HA_EXTRA_INSERT_WITH_UPDATE);
 
1820
  table->file->ha_start_bulk_insert((ha_rows) 0);
1666
1821
  session->abort_on_warning= !info.ignore;
1667
1822
  if (check_that_all_fields_are_given_values(session, table, table_list))
1668
1823
    return(1);
1669
1824
  table->mark_columns_needed_for_insert();
1670
 
  table->cursor->extra(HA_EXTRA_WRITE_CACHE);
 
1825
  table->file->extra(HA_EXTRA_WRITE_CACHE);
1671
1826
  return(0);
1672
1827
}
1673
1828
 
 
1829
void
 
1830
select_create::binlog_show_create_table(Table **tables, uint32_t count)
 
1831
{
 
1832
  /*
 
1833
    Note 1: In RBR mode, we generate a CREATE TABLE statement for the
 
1834
    created table by calling store_create_info() (behaves as SHOW
 
1835
    CREATE TABLE).  In the event of an error, nothing should be
 
1836
    written to the binary log, even if the table is non-transactional;
 
1837
    therefore we pretend that the generated CREATE TABLE statement is
 
1838
    for a transactional table.  The event will then be put in the
 
1839
    transaction cache, and any subsequent events (e.g., table-map
 
1840
    events and binrow events) will also be put there.  We can then use
 
1841
    ha_autocommit_or_rollback() to either throw away the entire
 
1842
    kaboodle of events, or write them to the binary log.
 
1843
 
 
1844
    We write the CREATE TABLE statement here and not in prepare()
 
1845
    since there potentially are sub-selects or accesses to information
 
1846
    schema that will do a close_thread_tables(), destroying the
 
1847
    statement transaction cache.
 
1848
  */
 
1849
  assert(tables && *tables && count > 0);
 
1850
 
 
1851
  char buf[2048];
 
1852
  String query(buf, sizeof(buf), system_charset_info);
 
1853
  int result;
 
1854
  TableList tmp_table_list;
 
1855
 
 
1856
  memset(&tmp_table_list, 0, sizeof(tmp_table_list));
 
1857
  tmp_table_list.table = *tables;
 
1858
  query.length(0);      // Have to zero it since constructor doesn't
 
1859
 
 
1860
  result= store_create_info(session, &tmp_table_list, &query, create_info);
 
1861
  assert(result == 0); /* store_create_info() always return 0 */
 
1862
 
 
1863
  session->binlog_query(Session::STMT_QUERY_TYPE,
 
1864
                    query.ptr(), query.length(),
 
1865
                    /* is_trans */ true,
 
1866
                    /* suppress_use */ false);
 
1867
}
 
1868
 
1674
1869
void select_create::store_values(List<Item> &values)
1675
1870
{
1676
 
  fill_record(session, field, values, true);
 
1871
  fill_record(session, field, values, 1);
1677
1872
}
1678
1873
 
1679
1874
 
1680
1875
void select_create::send_error(uint32_t errcode,const char *err)
1681
1876
{
 
1877
  
 
1878
 
1682
1879
  /*
1683
1880
    This will execute any rollbacks that are necessary before writing
1684
1881
    the transcation cache.
1690
1887
    written to the binary log.
1691
1888
 
1692
1889
  */
 
1890
  tmp_disable_binlog(session);
1693
1891
  select_insert::send_error(errcode, err);
 
1892
  reenable_binlog(session);
1694
1893
 
1695
1894
  return;
1696
1895
}
1710
1909
    */
1711
1910
    if (!table->s->tmp_table)
1712
1911
    {
1713
 
      TransactionServices &transaction_services= TransactionServices::singleton();
1714
 
      transaction_services.autocommitOrRollback(session, 0);
1715
 
      (void) session->endActiveTransaction();
 
1912
      ha_autocommit_or_rollback(session, 0);
 
1913
      end_active_trans(session);
1716
1914
    }
1717
1915
 
1718
 
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1719
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
1916
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1917
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1720
1918
    if (m_plock)
1721
1919
    {
1722
1920
      mysql_unlock_tables(session, *m_plock);
1730
1928
 
1731
1929
void select_create::abort()
1732
1930
{
 
1931
  
 
1932
 
1733
1933
  /*
1734
1934
    In select_insert::abort() we roll back the statement, including
1735
1935
    truncating the transaction cache of the binary log. To do this, we
1745
1945
    of the table succeeded or not, since we need to reset the binary
1746
1946
    log state.
1747
1947
  */
 
1948
  tmp_disable_binlog(session);
1748
1949
  select_insert::abort();
 
1950
  session->transaction.stmt.modified_non_trans_table= false;
 
1951
  reenable_binlog(session);
 
1952
 
1749
1953
 
1750
1954
  if (m_plock)
1751
1955
  {
1756
1960
 
1757
1961
  if (table)
1758
1962
  {
1759
 
    table->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1760
 
    table->cursor->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
1761
 
    if (not create_info->table_existed)
1762
 
      session->drop_open_table(table, identifier);
1763
 
    table= NULL;                                    // Safety
 
1963
    table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
 
1964
    table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
 
1965
    if (!create_info->table_existed)
 
1966
      drop_open_table(session, table, create_table->db, create_table->table_name);
 
1967
    table=0;                                    // Safety
1764
1968
  }
 
1969
  return;
1765
1970
}
1766
1971
 
1767
 
} /* namespace drizzled */
 
1972
 
 
1973
/*****************************************************************************
 
1974
  Instansiate templates
 
1975
*****************************************************************************/
 
1976
 
 
1977
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
 
1978
template class List_iterator_fast<List_item>;
 
1979
#endif /* HAVE_EXPLICIT_TEMPLATE_INSTANTIATION */