~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/foreign_key.cc

Merge Monty.

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
 
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
#include "config.h"
 
21
 
 
22
#include <string>
 
23
 
 
24
#include "drizzled/foreign_key.h"
 
25
#include "drizzled/error.h"
 
26
#include "drizzled/create_field.h"
 
27
#include "drizzled/internal/my_sys.h"
 
28
 
 
29
using namespace drizzled;
 
30
 
 
31
extern const CHARSET_INFO *system_charset_info;
 
32
 
 
33
Foreign_key::Foreign_key(const Foreign_key &rhs, memory::Root *mem_root)
 
34
  :Key(rhs),
 
35
  ref_table(rhs.ref_table),
 
36
  ref_columns(rhs.ref_columns),
 
37
  delete_opt(rhs.delete_opt),
 
38
  update_opt(rhs.update_opt),
 
39
  match_opt(rhs.match_opt)
 
40
{
 
41
  list_copy_and_replace_each_value(ref_columns, mem_root);
 
42
}
 
43
 
 
44
/*
 
45
  Test if a foreign key (= generated key) is a prefix of the given key
 
46
  (ignoring key name, key type and order of columns)
 
47
 
 
48
  NOTES:
 
49
    This is only used to test if an index for a FOREIGN KEY exists
 
50
 
 
51
  IMPLEMENTATION
 
52
    We only compare field names
 
53
 
 
54
  RETURN
 
55
    0   Generated key is a prefix of other key
 
56
    1   Not equal
 
57
*/
 
58
bool foreign_key_prefix(Key *a, Key *b)
 
59
{
 
60
  /* Ensure that 'a' is the generated key */
 
61
  if (a->generated)
 
62
  {
 
63
    if (b->generated && a->columns.elements > b->columns.elements)
 
64
      std::swap(a, b);                       // Put shorter key in 'a'
 
65
  }
 
66
  else
 
67
  {
 
68
    if (!b->generated)
 
69
      return true;                              // No foreign key
 
70
    std::swap(a, b);                       // Put generated key in 'a'
 
71
  }
 
72
 
 
73
  /* Test if 'a' is a prefix of 'b' */
 
74
  if (a->columns.elements > b->columns.elements)
 
75
    return true;                                // Can't be prefix
 
76
 
 
77
  List_iterator<Key_part_spec> col_it1(a->columns);
 
78
  List_iterator<Key_part_spec> col_it2(b->columns);
 
79
  const Key_part_spec *col1, *col2;
 
80
 
 
81
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
 
82
  while ((col1= col_it1++))
 
83
  {
 
84
    bool found= 0;
 
85
    col_it2.rewind();
 
86
    while ((col2= col_it2++))
 
87
    {
 
88
      if (*col1 == *col2)
 
89
      {
 
90
        found= true;
 
91
        break;
 
92
      }
 
93
    }
 
94
    if (!found)
 
95
      return true;                              // Error
 
96
  }
 
97
  return false;                                 // Is prefix
 
98
#else
 
99
  while ((col1= col_it1++))
 
100
  {
 
101
    col2= col_it2++;
 
102
    if (!(*col1 == *col2))
 
103
      return true;
 
104
  }
 
105
  return false;                                 // Is prefix
 
106
#endif
 
107
}
 
108
 
 
109
/*
 
110
  Check if the foreign key options are compatible with columns
 
111
  on which the FK is created.
 
112
 
 
113
  RETURN
 
114
    0   Key valid
 
115
    1   Key invalid
 
116
*/
 
117
bool Foreign_key::validate(List<CreateField> &table_fields)
 
118
{
 
119
  CreateField  *sql_field;
 
120
  Key_part_spec *column;
 
121
  List_iterator<Key_part_spec> cols(columns);
 
122
  List_iterator<CreateField> it(table_fields);
 
123
  while ((column= cols++))
 
124
  {
 
125
    it.rewind();
 
126
    while ((sql_field= it++) &&
 
127
           my_strcasecmp(system_charset_info,
 
128
                         column->field_name.str,
 
129
                         sql_field->field_name)) {}
 
130
    if (!sql_field)
 
131
    {
 
132
      my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
 
133
      return true;
 
134
    }
 
135
  }
 
136
  return false;
 
137
}
 
138
 
 
139
 
 
140