~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/foreign_key.cc

  • Committer: Jay Pipes
  • Date: 2009-03-19 23:04:21 UTC
  • mto: This revision was merged to the branch mainline in revision 957.
  • Revision ID: jpipes@serialcoder-20090319230421-x7yfjzfy34aon7uj
Move Foreign_key implementation into its own implementation file and out of session.cc

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