~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_list.h

  • Committer: Jim Winstead
  • Date: 2008-07-19 02:56:45 UTC
  • mto: (202.1.8 codestyle)
  • mto: This revision was merged to the branch mainline in revision 207.
  • Revision ID: jimw@mysql.com-20080719025645-w2pwytebgzusjzjb
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
Temporarily disables tab-completion in the drizzle client until an appropriate
autoconf check can be added/enabled.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#ifndef DRIZZLED_SQL_LIST_H
21
 
#define DRIZZLED_SQL_LIST_H
22
 
 
23
 
#include <cstdlib>
24
 
#include <cassert>
25
 
#include <utility>
26
 
#include <algorithm>
27
 
#include <drizzled/memory/sql_alloc.h>
28
 
#include <drizzled/visibility.h>
29
 
 
30
 
namespace drizzled {
31
 
 
32
 
typedef struct st_sql_list 
 
1
#ifndef INCLUDES_MYSQL_SQL_LIST_H
 
2
#define INCLUDES_MYSQL_SQL_LIST_H
 
3
/* Copyright (C) 2000-2003 MySQL AB
 
4
 
 
5
   This program is free software; you can redistribute it and/or modify
 
6
   it under the terms of the GNU General Public License as published by
 
7
   the Free Software Foundation; version 2 of the License.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with this program; if not, write to the Free Software
 
16
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
17
 
 
18
 
 
19
#ifdef USE_PRAGMA_INTERFACE
 
20
#pragma interface                       /* gcc class implementation */
 
21
#endif
 
22
 
 
23
/* mysql standard class memory allocator */
 
24
 
 
25
class Sql_alloc
33
26
{
34
 
  uint32_t elements;
35
 
  unsigned char *first;
36
 
  unsigned char **next;
37
 
 
38
 
  inline void clear()
39
 
  {
40
 
    elements=0;
41
 
    first=0;
42
 
    next= &first;
43
 
  }
44
 
  inline void link_in_list(unsigned char *element,unsigned char **next_ptr)
45
 
  {
46
 
    elements++;
47
 
    (*next)=element;
48
 
    next= next_ptr;
49
 
    *next=0;
50
 
  }
51
 
  inline void save_and_clear(struct st_sql_list *save)
52
 
  {
53
 
    *save= *this;
54
 
    clear();
55
 
  }
56
 
  inline void push_front(struct st_sql_list *save)
57
 
  {
58
 
    *save->next= first;                         /* link current list last */
59
 
    first= save->first;
60
 
    elements+= save->elements;
61
 
  }
62
 
  inline void push_back(struct st_sql_list *save)
63
 
  {
64
 
    if (save->first)
65
 
    {
66
 
      *next= save->first;
67
 
      next= save->next;
68
 
      elements+= save->elements;
69
 
    }
70
 
  }
71
 
} SQL_LIST;
 
27
public:
 
28
  static void *operator new(size_t size) throw ()
 
29
  {
 
30
    return sql_alloc(size);
 
31
  }
 
32
  static void *operator new[](size_t size)
 
33
  {
 
34
    return sql_alloc(size);
 
35
  }
 
36
  static void *operator new[](size_t size, MEM_ROOT *mem_root) throw ()
 
37
  { return alloc_root(mem_root, size); }
 
38
  static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
 
39
  { return alloc_root(mem_root, size); }
 
40
  static void operator delete(void *ptr __attribute__((__unused__)),
 
41
                              size_t size __attribute__((__unused__)))
 
42
  { TRASH(ptr, size); }
 
43
  static void operator delete(void *ptr __attribute__((__unused__)),
 
44
                              MEM_ROOT *mem_root __attribute__((__unused__)))
 
45
  { /* never called */ }
 
46
  static void operator delete[](void *ptr __attribute__((__unused__)),
 
47
                                MEM_ROOT *mem_root __attribute__((__unused__)))
 
48
  { /* never called */ }
 
49
  static void operator delete[](void *ptr __attribute__((__unused__)),
 
50
                                size_t size __attribute__((__unused__)))
 
51
  { TRASH(ptr, size); }
 
52
#ifdef HAVE_purify
 
53
  bool dummy;
 
54
  inline Sql_alloc() :dummy(0) {}
 
55
  inline ~Sql_alloc() {}
 
56
#else
 
57
  inline Sql_alloc() {}
 
58
  inline ~Sql_alloc() {}
 
59
#endif
 
60
 
 
61
};
 
62
 
72
63
 
73
64
/*
74
65
  Basic single linked list
86
77
  @note We never call a destructor for instances of this class.
87
78
*/
88
79
 
89
 
struct list_node : public memory::SqlAlloc
 
80
struct list_node :public Sql_alloc
90
81
{
91
82
  list_node *next;
92
83
  void *info;
101
92
};
102
93
 
103
94
 
104
 
extern DRIZZLED_API list_node end_of_list;
 
95
extern list_node end_of_list;
105
96
 
106
 
class base_list :public memory::SqlAlloc
 
97
class base_list :public Sql_alloc
107
98
{
108
99
protected:
109
100
  list_node *first,**last;
110
101
 
111
102
public:
112
 
  uint32_t elements;
 
103
  uint elements;
113
104
 
114
 
  inline void clear() { elements=0; first= &end_of_list; last=&first;}
115
 
  inline base_list() { clear(); }
 
105
  inline void empty() { elements=0; first= &end_of_list; last=&first;}
 
106
  inline base_list() { empty(); }
116
107
  /**
117
108
    This is a shallow copy constructor that implicitly passes the ownership
118
109
    from the source list to the new instance. The old instance is not
122
113
    relies on this behaviour. This logic is quite tricky: please do not use
123
114
    it in any new code.
124
115
  */
125
 
  inline base_list(const base_list &tmp) :memory::SqlAlloc()
 
116
  inline base_list(const base_list &tmp) :Sql_alloc()
126
117
  {
127
118
    elements= tmp.elements;
128
119
    first= tmp.first;
129
120
    last= elements ? tmp.last : &first;
130
121
  }
131
 
  inline base_list(bool) { }
 
122
  /**
 
123
    Construct a deep copy of the argument in memory root mem_root.
 
124
    The elements themselves are copied by pointer. If you also
 
125
    need to copy elements by value, you should employ
 
126
    list_copy_and_replace_each_value after creating a copy.
 
127
  */
 
128
  base_list(const base_list &rhs, MEM_ROOT *mem_root);
 
129
  inline base_list(bool error __attribute__((__unused__))) { }
132
130
  inline bool push_back(void *info)
133
131
  {
134
132
    if (((*last)=new list_node(info, &end_of_list)))
139
137
    }
140
138
    return 1;
141
139
  }
142
 
  inline bool push_back(void *info, memory::Root *mem_root)
 
140
  inline bool push_back(void *info, MEM_ROOT *mem_root)
143
141
  {
144
142
    if (((*last)=new (mem_root) list_node(info, &end_of_list)))
145
143
    {
219
217
  */
220
218
  inline void swap(base_list &rhs)
221
219
  {
222
 
    std::swap(first, rhs.first);
223
 
    std::swap(last, rhs.last);
224
 
    std::swap(elements, rhs.elements);
 
220
    swap_variables(list_node *, first, rhs.first);
 
221
    swap_variables(list_node **, last, rhs.last);
 
222
    swap_variables(uint, elements, rhs.elements);
225
223
  }
226
224
  inline list_node* last_node() { return *last; }
227
225
  inline list_node* first_node() { return first;}
230
228
  inline bool is_empty() { return first == &end_of_list ; }
231
229
  inline list_node *last_ref() { return &end_of_list; }
232
230
  friend class base_list_iterator;
 
231
  friend class error_list;
 
232
  friend class error_list_iterator;
233
233
 
234
234
#ifdef LIST_EXTRA_DEBUG
235
235
  /*
242
242
      check_list()
243
243
        name  Name to print to trace file
244
244
 
245
 
    RETURN
 
245
    RETURN 
246
246
      1  The list is Ok.
247
247
      0  List invariants are not met.
248
248
  */
251
251
  {
252
252
    base_list *list= this;
253
253
    list_node *node= first;
254
 
    uint32_t cnt= 0;
 
254
    uint cnt= 0;
255
255
 
256
256
    while (node->next != &end_of_list)
257
257
    {
291
291
protected:
292
292
  base_list *list;
293
293
  list_node **el,**prev,*current;
294
 
public:
295
 
  void sublist(base_list &ls, uint32_t elm)
 
294
  void sublist(base_list &ls, uint elm)
296
295
  {
297
296
    ls.first= *el;
298
297
    ls.last= list->last;
299
298
    ls.elements= elm;
300
299
  }
301
 
  base_list_iterator()
 
300
public:
 
301
  base_list_iterator() 
302
302
    :list(0), el(0), prev(0), current(0)
303
303
  {}
304
304
 
305
 
  base_list_iterator(base_list &list_par, list_node** el0)
306
 
    :list(&list_par), el(el0), prev(0), current(0)
 
305
  base_list_iterator(base_list &list_par) 
 
306
  { init(list_par); }
 
307
 
 
308
  inline void init(base_list &list_par)
307
309
  {
 
310
    list= &list_par;
 
311
    el= &list_par.first;
 
312
    prev= 0;
 
313
    current= 0;
308
314
  }
309
315
 
310
316
  inline void *next(void)
314
320
    el= &current->next;
315
321
    return current->info;
316
322
  }
 
323
  inline void *next_fast(void)
 
324
  {
 
325
    list_node *tmp;
 
326
    tmp= *el;
 
327
    el= &tmp->next;
 
328
    return tmp->info;
 
329
  }
 
330
  inline void rewind(void)
 
331
  {
 
332
    el= &list->first;
 
333
  }
317
334
  inline void *replace(void *element)
318
335
  {                                             // Return old element
319
336
    void *tmp=current->info;
355
372
  {
356
373
    return el == &list->last_ref()->next;
357
374
  }
 
375
  friend class error_list_iterator;
358
376
};
359
377
 
360
 
template <class T> class List_iterator;
361
 
 
362
378
template <class T> class List :public base_list
363
379
{
364
380
public:
365
 
  typedef List_iterator<T> iterator;
366
 
 
367
 
  friend class List_iterator<T>;
368
 
 
369
381
  inline List() :base_list() {}
370
382
  inline List(const List<T> &tmp) :base_list(tmp) {}
371
 
  inline List(const List<T> &tmp, memory::Root *mem_root) :
 
383
  inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
372
384
    base_list(tmp, mem_root) {}
373
385
  inline bool push_back(T *a) { return base_list::push_back(a); }
374
 
  inline bool push_back(T *a, memory::Root *mem_root)
 
386
  inline bool push_back(T *a, MEM_ROOT *mem_root)
375
387
  { return base_list::push_back(a, mem_root); }
376
388
  inline bool push_front(T *a) { return base_list::push_front(a); }
377
 
  inline T* head() {return static_cast<T*>(base_list::head()); }
378
 
  inline T* pop()  {return static_cast<T*>(base_list::pop()); }
 
389
  inline T* head() {return (T*) base_list::head(); }
 
390
  inline T** head_ref() {return (T**) base_list::head_ref(); }
 
391
  inline T* pop()  {return (T*) base_list::pop(); }
379
392
  inline void concat(List<T> *list) { base_list::concat(list); }
380
393
  inline void disjoin(List<T> *list) { base_list::disjoin(list); }
381
394
  inline void prepand(List<T> *list) { base_list::prepand(list); }
387
400
      next=element->next;
388
401
      delete (T*) element->info;
389
402
    }
390
 
    clear();
391
 
  }
392
 
 
393
 
  iterator begin()
394
 
  {
395
 
    return iterator(*this, &first);
 
403
    empty();
396
404
  }
397
405
};
398
406
 
400
408
template <class T> class List_iterator :public base_list_iterator
401
409
{
402
410
public:
403
 
  List_iterator(List<T>& a, list_node** b) : base_list_iterator(a, b) {};
404
 
  List_iterator() {};
 
411
  List_iterator(List<T> &a) : base_list_iterator(a) {}
 
412
  List_iterator() : base_list_iterator() {}
 
413
  inline void init(List<T> &a) { base_list_iterator::init(a); }
405
414
  inline T* operator++(int) { return (T*) base_list_iterator::next(); }
406
415
  inline T *replace(T *a)   { return (T*) base_list_iterator::replace(a); }
407
416
  inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
 
417
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
418
  inline void remove()      { base_list_iterator::remove(); }
 
419
  inline void after(T *a)   { base_list_iterator::after(a); }
408
420
  inline T** ref(void)      { return (T**) base_list_iterator::ref(); }
409
421
};
410
422
 
 
423
 
 
424
template <class T> class List_iterator_fast :public base_list_iterator
 
425
{
 
426
protected:
 
427
  inline T *replace(T *a __attribute__((__unused__)))   { return (T*) 0; }
 
428
  inline T *replace(List<T> &a __attribute__((__unused__))) { return (T*) 0; }
 
429
  inline void remove(void)  { }
 
430
  inline void after(T *a __attribute__((__unused__)))   { }
 
431
  inline T** ref(void)      { return (T**) 0; }
 
432
 
 
433
public:
 
434
  inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
 
435
  inline List_iterator_fast() : base_list_iterator() {}
 
436
  inline void init(List<T> &a) { base_list_iterator::init(a); }
 
437
  inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
 
438
  inline void rewind(void)  { base_list_iterator::rewind(); }
 
439
  void sublist(List<T> &list_arg, uint el_arg)
 
440
  {
 
441
    base_list_iterator::sublist(list_arg, el_arg);
 
442
  }
 
443
};
 
444
 
 
445
 
 
446
/*
 
447
  A simple intrusive list which automaticly removes element from list
 
448
  on delete (for THD element)
 
449
*/
 
450
 
 
451
struct ilink
 
452
{
 
453
  struct ilink **prev,*next;
 
454
  static void *operator new(size_t size)
 
455
  {
 
456
    return (void*)my_malloc((uint)size, MYF(MY_WME | MY_FAE | ME_FATALERROR));
 
457
  }
 
458
  static void operator delete(void* ptr_arg,
 
459
                              size_t size __attribute__((__unused__)))
 
460
  {
 
461
     my_free((uchar*)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
 
462
  }
 
463
 
 
464
  inline ilink()
 
465
  {
 
466
    prev=0; next=0;
 
467
  }
 
468
  inline void unlink()
 
469
  {
 
470
    /* Extra tests because element doesn't have to be linked */
 
471
    if (prev) *prev= next;
 
472
    if (next) next->prev=prev;
 
473
    prev=0 ; next=0;
 
474
  }
 
475
  virtual ~ilink() { unlink(); }                /*lint -e1740 */
 
476
};
 
477
 
 
478
 
 
479
/* Needed to be able to have an I_List of char* strings in mysqld.cc. */
 
480
 
 
481
class i_string: public ilink
 
482
{
 
483
public:
 
484
  const char* ptr;
 
485
  i_string():ptr(0) { }
 
486
  i_string(const char* s) : ptr(s) {}
 
487
};
 
488
 
 
489
/* needed for linked list of two strings for replicate-rewrite-db */
 
490
class i_string_pair: public ilink
 
491
{
 
492
public:
 
493
  const char* key;
 
494
  const char* val;
 
495
  i_string_pair():key(0),val(0) { }
 
496
  i_string_pair(const char* key_arg, const char* val_arg) : 
 
497
    key(key_arg),val(val_arg) {}
 
498
};
 
499
 
 
500
 
 
501
template <class T> class I_List_iterator;
 
502
 
 
503
/*
 
504
  WARNING: copy constructor of this class does not create a usable
 
505
  copy, as its members may point at each other.
 
506
*/
 
507
 
 
508
class base_ilist
 
509
{
 
510
public:
 
511
  struct ilink *first,last;
 
512
  inline void empty() { first= &last; last.prev= &first; }
 
513
  base_ilist() { empty(); }
 
514
  inline bool is_empty() {  return first == &last; }
 
515
  inline void append(ilink *a)
 
516
  {
 
517
    first->prev= &a->next;
 
518
    a->next=first; a->prev= &first; first=a;
 
519
  }
 
520
  inline void push_back(ilink *a)
 
521
  {
 
522
    *last.prev= a;
 
523
    a->next= &last;
 
524
    a->prev= last.prev;
 
525
    last.prev= &a->next;
 
526
  }
 
527
  inline struct ilink *get()
 
528
  {
 
529
    struct ilink *first_link=first;
 
530
    if (first_link == &last)
 
531
      return 0;
 
532
    first_link->unlink();                       // Unlink from list
 
533
    return first_link;
 
534
  }
 
535
  inline struct ilink *head()
 
536
  {
 
537
    return (first != &last) ? first : 0;
 
538
  }
 
539
  friend class base_list_iterator;
 
540
};
 
541
 
 
542
 
 
543
class base_ilist_iterator
 
544
{
 
545
  base_ilist *list;
 
546
  struct ilink **el,*current;
 
547
public:
 
548
  base_ilist_iterator(base_ilist &list_par) :list(&list_par),
 
549
    el(&list_par.first),current(0) {}
 
550
  void *next(void)
 
551
  {
 
552
    /* This is coded to allow push_back() while iterating */
 
553
    current= *el;
 
554
    if (current == &list->last) return 0;
 
555
    el= &current->next;
 
556
    return current;
 
557
  }
 
558
};
 
559
 
 
560
 
 
561
template <class T>
 
562
class I_List :private base_ilist
 
563
{
 
564
public:
 
565
  I_List() :base_ilist()        {}
 
566
  inline void empty()           { base_ilist::empty(); }
 
567
  inline bool is_empty()        { return base_ilist::is_empty(); } 
 
568
  inline void append(T* a)      { base_ilist::append(a); }
 
569
  inline void push_back(T* a)   { base_ilist::push_back(a); }
 
570
  inline T* get()               { return (T*) base_ilist::get(); }
 
571
  inline T* head()              { return (T*) base_ilist::head(); }
 
572
#ifndef _lint
 
573
  friend class I_List_iterator<T>;
 
574
#endif
 
575
};
 
576
 
 
577
 
 
578
template <class T> class I_List_iterator :public base_ilist_iterator
 
579
{
 
580
public:
 
581
  I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
 
582
  inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
 
583
};
 
584
 
411
585
/**
412
586
  Make a deep copy of each list element.
413
587
 
419
593
  Evidently not all template arguments have clone() method with
420
594
  the right signature.
421
595
 
422
 
  @return You must query the error state in Session for out-of-memory
 
596
  @return You must query the error state in THD for out-of-memory
423
597
  situation after calling this function.
424
598
*/
425
599
 
426
600
template <typename T>
427
 
void list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
 
601
inline
 
602
void
 
603
list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
428
604
{
429
605
  /* Make a deep copy of each element */
430
 
  typename List<T>::iterator it(list.begin());
 
606
  List_iterator<T> it(list);
431
607
  T *el;
432
608
  while ((el= it++))
433
609
    it.replace(el->clone(mem_root));
434
610
}
435
611
 
436
 
} /* namespace drizzled */
437
 
 
438
 
#endif /* DRIZZLED_SQL_LIST_H */
 
612
#endif // INCLUDES_MYSQL_SQL_LIST_H