00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <string>
00023
00024 #include <drizzled/foreign_key.h>
00025 #include <drizzled/error.h>
00026 #include <drizzled/create_field.h>
00027 #include <drizzled/internal/my_sys.h>
00028 #include <drizzled/table_ident.h>
00029
00030 namespace drizzled
00031 {
00032
00033 extern const CHARSET_INFO *system_charset_info;
00034
00035 void add_foreign_key_to_table_message(
00036 message::Table *table_message,
00037 const char* fkey_name,
00038 List<Key_part_spec> &cols,
00039 Table_ident *table,
00040 List<Key_part_spec> &ref_cols,
00041 message::Table::ForeignKeyConstraint::ForeignKeyOption delete_opt_arg,
00042 message::Table::ForeignKeyConstraint::ForeignKeyOption update_opt_arg,
00043 message::Table::ForeignKeyConstraint::ForeignKeyMatchOption match_opt_arg)
00044 {
00045 message::Table::ForeignKeyConstraint *pfkey= table_message->add_fk_constraint();
00046 if (fkey_name)
00047 pfkey->set_name(fkey_name);
00048 else if (table_message->has_name())
00049 {
00050 std::string name(table_message->name());
00051 char number[20];
00052
00053 name.append("_ibfk_");
00054 snprintf(number, sizeof(number), "%d", table_message->fk_constraint_size());
00055 name.append(number);
00056
00057 pfkey->set_name(name);
00058 }
00059
00060 pfkey->set_match(match_opt_arg);
00061 pfkey->set_update_option(update_opt_arg);
00062 pfkey->set_delete_option(delete_opt_arg);
00063
00064 pfkey->set_references_table_name(table->table.str);
00065
00066 Key_part_spec *keypart;
00067 List<Key_part_spec>::iterator col_it(cols.begin());
00068 while ((keypart= col_it++))
00069 {
00070 pfkey->add_column_names(keypart->field_name.str);
00071 }
00072
00073 List<Key_part_spec>::iterator ref_it(ref_cols.begin());
00074 while ((keypart= ref_it++))
00075 {
00076 pfkey->add_references_columns(keypart->field_name.str);
00077 }
00078
00079 }
00080
00096 template <typename T>
00097 void list_copy_and_replace_each_value(List<T> &list, memory::Root *mem_root)
00098 {
00099
00100 typename List<T>::iterator it(list.begin());
00101 T *el;
00102 while ((el= it++))
00103 it.replace(el->clone(mem_root));
00104 }
00105
00106 Foreign_key::Foreign_key(const Foreign_key &rhs, memory::Root *mem_root)
00107 :Key(rhs),
00108 ref_table(rhs.ref_table),
00109 ref_columns(rhs.ref_columns),
00110 delete_opt(rhs.delete_opt),
00111 update_opt(rhs.update_opt),
00112 match_opt(rhs.match_opt)
00113 {
00114 list_copy_and_replace_each_value(ref_columns, mem_root);
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 bool foreign_key_prefix(Key *a, Key *b)
00132 {
00133
00134 if (a->generated)
00135 {
00136 if (b->generated && a->columns.size() > b->columns.size())
00137 std::swap(a, b);
00138 }
00139 else
00140 {
00141 if (!b->generated)
00142 return true;
00143 std::swap(a, b);
00144 }
00145
00146
00147 if (a->columns.size() > b->columns.size())
00148 return true;
00149
00150 List<Key_part_spec>::iterator col_it1(a->columns.begin());
00151 List<Key_part_spec>::iterator col_it2(b->columns.begin());
00152 const Key_part_spec *col1, *col2;
00153
00154 #ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
00155 while ((col1= col_it1++))
00156 {
00157 bool found= 0;
00158 col_it2=b->columns.begin();
00159 while ((col2= col_it2++))
00160 {
00161 if (*col1 == *col2)
00162 {
00163 found= true;
00164 break;
00165 }
00166 }
00167 if (!found)
00168 return true;
00169 }
00170 return false;
00171 #else
00172 while ((col1= col_it1++))
00173 {
00174 col2= col_it2++;
00175 if (!(*col1 == *col2))
00176 return true;
00177 }
00178 return false;
00179 #endif
00180 }
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 bool Foreign_key::validate(List<CreateField> &table_fields)
00191 {
00192 CreateField *sql_field;
00193 Key_part_spec *column;
00194 List<Key_part_spec>::iterator cols(columns.begin());
00195 List<CreateField>::iterator it(table_fields.begin());
00196 while ((column= cols++))
00197 {
00198 it= table_fields.begin();
00199 while ((sql_field= it++) &&
00200 my_strcasecmp(system_charset_info,
00201 column->field_name.str,
00202 sql_field->field_name)) {}
00203 if (!sql_field)
00204 {
00205 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
00206 return true;
00207 }
00208 }
00209 return false;
00210 }
00211
00212 }