~drizzle-trunk/drizzle/development

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 *
 *  Copyright (C) 2008 Sun Microsystems, Inc.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef DRIZZLED_STORED_KEY_H
#define DRIZZLED_STORED_KEY_H

namespace drizzled
{

/** class to store an field/item as a key struct */
class StoredKey :public memory::SqlAlloc
{
public:
  bool null_key; /**< If true, the value of the key has a null part */
  enum store_key_result 
  { 
    STORE_KEY_OK,
    STORE_KEY_FATAL, 
    STORE_KEY_CONV 
  };
protected:
  Field *to_field;				// Store data here
  unsigned char *null_ptr;
  unsigned char err;
  virtual enum store_key_result copy_inner()=0;
public:
  StoredKey(Session *session,
            Field *field_arg, 
            unsigned char *ptr,
            unsigned char *null, 
            uint32_t length)
    :
      null_key(0), 
      null_ptr(null), 
      err(0)
  {
    if (field_arg->type() == DRIZZLE_TYPE_BLOB)
    {
      /*
        Key segments are always packed with a 2 byte length prefix.
        See mi_rkey for details.
      */
      to_field= new Field_varstring(ptr,
                                    length,
                                    2,
                                    null,
                                    1,
                                    field_arg->field_name,
                                    field_arg->charset());
      to_field->init(field_arg->getTable());
    }
    else
      to_field= field_arg->new_key_field(session->mem_root, field_arg->getTable(),
                                        ptr, null, 1);

    to_field->setWriteSet();
  }
  virtual ~StoredKey() {}			/** Not actually needed */
  virtual const char *name() const=0;

  /**
    @brief sets ignore truncation warnings mode and calls the real copy method

    @details this function makes sure truncation warnings when preparing the
    key buffers don't end up as errors (because of an enclosing INSERT/UPDATE).
  */
  enum store_key_result copy()
  {
    enum store_key_result result;
    Session *session= to_field->getTable()->in_use;
    enum_check_fields saved_count_cuted_fields= session->count_cuted_fields;
    session->count_cuted_fields= CHECK_FIELD_IGNORE;
    result= copy_inner();
    session->count_cuted_fields= saved_count_cuted_fields;

    return result;
  }
};

class store_key_field: public StoredKey
{
  CopyField copy_field;
  const char *field_name;
public:
  store_key_field(Session *session, Field *to_field_arg, unsigned char *ptr,
                  unsigned char *null_ptr_arg,
		  uint32_t length, Field *from_field, const char *name_arg)
    :StoredKey(session, to_field_arg,ptr,
	       null_ptr_arg ? null_ptr_arg : from_field->maybe_null() ? &err
	       : (unsigned char*) 0, length), field_name(name_arg)
  {
    if (to_field)
    {
      copy_field.set(to_field,from_field,0);
    }
  }
  const char *name() const { return field_name; }

protected:
  enum store_key_result copy_inner()
  {
    copy_field.do_copy(&copy_field);
    null_key= to_field->is_null();
    return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK;
  }
};

class store_key_item :public StoredKey
{
 protected:
  Item *item;
public:
  store_key_item(Session *session, Field *to_field_arg, unsigned char *ptr,
                 unsigned char *null_ptr_arg, uint32_t length, Item *item_arg)
    :StoredKey(session, to_field_arg, ptr,
	       null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
	       &err : (unsigned char*) 0, length), item(item_arg)
  {}
  const char *name() const { return "func"; }

 protected:
  enum store_key_result copy_inner()
  {
    int res= item->save_in_field(to_field, 1);
    null_key= to_field->is_null() || item->null_value;
    return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res);
  }
};

class store_key_const_item :public store_key_item
{
  bool inited;
public:
  store_key_const_item(Session *session, Field *to_field_arg, unsigned char *ptr,
		       unsigned char *null_ptr_arg, uint32_t length,
		       Item *item_arg)
    :store_key_item(session, to_field_arg,ptr,
		    null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
		    &err : (unsigned char*) 0, length, item_arg), inited(0)
  {
  }
  const char *name() const { return "const"; }

protected:
  enum store_key_result copy_inner()
  {
    int res;
    if (!inited)
    {
      inited=1;
      if ((res= item->save_in_field(to_field, 1)))
      {
        if (!err)
          err= res;
      }
    }
    null_key= to_field->is_null() || item->null_value;
    return (err > 2 ?  STORE_KEY_FATAL : (store_key_result) err);
  }
};

} /* namespace drizzled */

#endif /* DRIZZLED_STORED_KEY_H */