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