~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_list.h

  • Committer: Stewart Smith
  • Date: 2009-05-15 06:57:12 UTC
  • mto: (991.1.5 for-brian)
  • mto: This revision was merged to the branch mainline in revision 1022.
  • Revision ID: stewart@flamingspork.com-20090515065712-bmionylacjmexmmm
Make sql_mode=NO_AUTO_VALUE_ON_ZERO default for Drizzle.

Also fix DEFAULT keyword handling for auto-increment so that it defaults to
NULL and not 0 so that the following is valid and generates two auto-inc
values:

create table t1 (a int auto_increment primary key)
insert into t1 (a) values (default);
insert into t1 (a) values (default);

Important to note that 0 is no longer magic. So this gives you duplicate
primary key error:

insert into t1 (a) values(0);
insert into t1 (a) values(0);

as you've inserted the explicit value of 0 twice.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
3
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 
4
 *  Copyright (C) 2008 Sun Microsystems
5
5
 *
6
6
 *  This program is free software; you can redistribute it and/or modify
7
7
 *  it under the terms of the GNU General Public License as published by
21
21
#define DRIZZLED_SQL_LIST_H
22
22
 
23
23
 
24
 
#include <cstdlib>
25
 
#include <cassert>
26
24
#include <utility>
27
25
#include <algorithm>
28
 
#include "drizzled/memory/sql_alloc.h"
29
 
#include "drizzled/visibility.h"
30
 
 
31
 
 
32
 
namespace drizzled
33
 
{
 
26
#include <stdlib.h>
 
27
#include <drizzled/sql_alloc.h>
34
28
 
35
29
/** Struct to handle simple linked lists. */
36
30
typedef struct st_sql_list {
90
84
  @note We never call a destructor for instances of this class.
91
85
*/
92
86
 
93
 
struct list_node : public memory::SqlAlloc
 
87
struct list_node :public Sql_alloc
94
88
{
95
89
  list_node *next;
96
90
  void *info;
105
99
};
106
100
 
107
101
 
108
 
extern DRIZZLED_API list_node end_of_list;
 
102
extern list_node end_of_list;
109
103
 
110
 
class base_list :public memory::SqlAlloc
 
104
class base_list :public Sql_alloc
111
105
{
112
106
protected:
113
107
  list_node *first,**last;
126
120
    relies on this behaviour. This logic is quite tricky: please do not use
127
121
    it in any new code.
128
122
  */
129
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
123
  inline base_list(const base_list &tmp) :Sql_alloc()
130
124
  {
131
125
    elements= tmp.elements;
132
126
    first= tmp.first;
133
127
    last= elements ? tmp.last : &first;
134
128
  }
 
129
  /**
 
130
    Construct a deep copy of the argument in memory root mem_root.
 
131
    The elements themselves are copied by pointer. If you also
 
132
    need to copy elements by value, you should employ
 
133
    list_copy_and_replace_each_value after creating a copy.
 
134
  */
 
135
  base_list(const base_list &rhs, MEM_ROOT *mem_root);
135
136
  inline base_list(bool) { }
136
137
  inline bool push_back(void *info)
137
138
  {
143
144
    }
144
145
    return 1;
145
146
  }
146
 
  inline bool push_back(void *info, memory::Root *mem_root)
 
147
  inline bool push_back(void *info, MEM_ROOT *mem_root)
147
148
  {
148
149
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
149
150
    {
386
387
public:
387
388
  inline List() :base_list() {}
388
389
  inline List(const List<T> &tmp) :base_list(tmp) {}
389
 
  inline List(const List<T> &tmp, memory::Root *mem_root) :
 
390
  inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
390
391
    base_list(tmp, mem_root) {}
391
392
  inline bool push_back(T *a) { return base_list::push_back(a); }
392
 
  inline bool push_back(T *a, memory::Root *mem_root)
 
393
  inline bool push_back(T *a, MEM_ROOT *mem_root)
393
394
  { return base_list::push_back(a, mem_root); }
394
395
  inline bool push_front(T *a) { return base_list::push_front(a); }
395
396
  inline T* head() {return (T*) base_list::head(); }
433
434
  inline T *replace(T *)   { return (T*) 0; }
434
435
  inline T *replace(List<T> &) { return (T*) 0; }
435
436
  inline void remove(void)  { }
436
 
  inline void after(T *)   { }
 
437
  inline void after(T *a)   { }
437
438
  inline T** ref(void)      { return (T**) 0; }
438
439
 
439
440
public:
449
450
};
450
451
 
451
452
 
 
453
/*
 
454
  A simple intrusive list which automaticly removes element from list
 
455
  on delete (for Session element)
 
456
*/
 
457
 
 
458
struct ilink
 
459
{
 
460
  struct ilink **prev,*next;
 
461
  static void *operator new(size_t size)
 
462
  {
 
463
    return (void*)malloc((uint32_t)size);
 
464
  }
 
465
  static void operator delete(void* ptr_arg, size_t)
 
466
  {
 
467
     free((unsigned char*)ptr_arg);
 
468
  }
 
469
 
 
470
  inline ilink()
 
471
  {
 
472
    prev=0; next=0;
 
473
  }
 
474
  inline void unlink()
 
475
  {
 
476
    /* Extra tests because element doesn't have to be linked */
 
477
    if (prev) *prev= next;
 
478
    if (next) next->prev=prev;
 
479
    prev=0 ; next=0;
 
480
  }
 
481
  virtual ~ilink() { unlink(); }                /*lint -e1740 */
 
482
};
 
483
 
 
484
 
 
485
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
 
486
 
 
487
class i_string: public ilink
 
488
{
 
489
public:
 
490
  const char* ptr;
 
491
  i_string():ptr(0) { }
 
492
  i_string(const char* s) : ptr(s) {}
 
493
};
 
494
 
 
495
/* needed for linked list of two strings for replicate-rewrite-db */
 
496
class i_string_pair: public ilink
 
497
{
 
498
public:
 
499
  const char* key;
 
500
  const char* val;
 
501
  i_string_pair():key(0),val(0) { }
 
502
  i_string_pair(const char* key_arg, const char* val_arg) :
 
503
    key(key_arg),val(val_arg) {}
 
504
};
 
505
 
 
506
 
 
507
template <class T> class I_List_iterator;
 
508
 
 
509
/*
 
510
  WARNING: copy constructor of this class does not create a usable
 
511
  copy, as its members may point at each other.
 
512
*/
 
513
 
 
514
class base_ilist
 
515
{
 
516
public:
 
517
  struct ilink *first,last;
 
518
  inline void empty() { first= &last; last.prev= &first; }
 
519
  base_ilist() { empty(); }
 
520
  inline bool is_empty() {  return first == &last; }
 
521
  inline void append(ilink *a)
 
522
  {
 
523
    first->prev= &a->next;
 
524
    a->next=first; a->prev= &first; first=a;
 
525
  }
 
526
  inline void push_back(ilink *a)
 
527
  {
 
528
    *last.prev= a;
 
529
    a->next= &last;
 
530
    a->prev= last.prev;
 
531
    last.prev= &a->next;
 
532
  }
 
533
  inline struct ilink *get()
 
534
  {
 
535
    struct ilink *first_link=first;
 
536
    if (first_link == &last)
 
537
      return 0;
 
538
    first_link->unlink();                       // Unlink from list
 
539
    return first_link;
 
540
  }
 
541
  inline struct ilink *head()
 
542
  {
 
543
    return (first != &last) ? first : 0;
 
544
  }
 
545
  friend class base_list_iterator;
 
546
};
 
547
 
 
548
 
 
549
class base_ilist_iterator
 
550
{
 
551
  base_ilist *list;
 
552
  struct ilink **el,*current;
 
553
public:
 
554
  base_ilist_iterator(base_ilist &list_par) :list(&list_par),
 
555
    el(&list_par.first),current(0) {}
 
556
  void *next(void)
 
557
  {
 
558
    /* This is coded to allow push_back() while iterating */
 
559
    current= *el;
 
560
    if (current == &list->last) return 0;
 
561
    el= &current->next;
 
562
    return current;
 
563
  }
 
564
};
 
565
 
 
566
 
 
567
template <class T>
 
568
class I_List :private base_ilist
 
569
{
 
570
public:
 
571
  I_List() :base_ilist()        {}
 
572
  inline void empty()           { base_ilist::empty(); }
 
573
  inline bool is_empty()        { return base_ilist::is_empty(); }
 
574
  inline void append(T* a)      { base_ilist::append(a); }
 
575
  inline void push_back(T* a)   { base_ilist::push_back(a); }
 
576
  inline T* get()               { return (T*) base_ilist::get(); }
 
577
  inline T* head()              { return (T*) base_ilist::head(); }
 
578
#ifndef _lint
 
579
  friend class I_List_iterator<T>;
 
580
#endif
 
581
};
 
582
 
 
583
 
 
584
template <class T> class I_List_iterator :public base_ilist_iterator
 
585
{
 
586
public:
 
587
  I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
 
588
  inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
 
589
};
 
590
 
452
591
/**
453
592
  Make a deep copy of each list element.
454
593
 
467
606
template <typename T>
468
607
inline
469
608
void
470
 
list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
 
609
list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
471
610
{
472
611
  /* Make a deep copy of each element */
473
612
  List_iterator<T> it(list);
476
615
    it.replace(el->clone(mem_root));
477
616
}
478
617
 
479
 
} /* namespace drizzled */
480
 
 
481
 
#endif /* DRIZZLED_SQL_LIST_H */
 
618
/* sql_list.cc */
 
619
void free_list(I_List <i_string_pair> *list);
 
620
void free_list(I_List <i_string> *list);
 
621
 
 
622
 
 
623
#endif // DRIZZLED_SQL_LIST_H