diff options
author | unknown <monty@mashka.mysql.fi> | 2002-10-02 17:55:12 +0300 |
---|---|---|
committer | unknown <monty@mashka.mysql.fi> | 2002-10-02 17:55:12 +0300 |
commit | 95e772b65678b182bff5b52f3f5386d894419147 (patch) | |
tree | a7ce8fe730bd0e06166bb15edcbe5aef252c2c3b /sql/sql_table.cc | |
parent | ff8f00774a6ad48b1b06ab498e415676d3fb707f (diff) | |
parent | 896bc7d08912a605d7c9ac9790a7bbf95d34ff08 (diff) | |
download | mariadb-git-95e772b65678b182bff5b52f3f5386d894419147.tar.gz |
Merge with 4.0.4
BitKeeper/etc/logging_ok:
auto-union
client/mysqldump.c:
Auto merged
include/Makefile.am:
Auto merged
include/my_base.h:
Auto merged
include/my_sys.h:
Auto merged
include/sslopt-case.h:
Auto merged
libmysql/libmysql.c:
Auto merged
libmysql/libmysql.def:
Auto merged
libmysqld/lib_sql.cc:
Auto merged
myisam/ft_boolean_search.c:
Auto merged
myisam/mi_check.c:
Auto merged
myisam/mi_create.c:
Auto merged
myisam/myisamchk.c:
Auto merged
mysql-test/mysql-test-run.sh:
Auto merged
mysql-test/r/create.result:
Auto merged
mysql-test/r/innodb.result:
Auto merged
mysql-test/r/myisam.result:
Auto merged
mysql-test/r/select.result:
Auto merged
mysql-test/r/type_set.result:
Auto merged
mysql-test/t/create.test:
Auto merged
mysql-test/t/myisam.test:
Auto merged
sql/Makefile.am:
Auto merged
sql/filesort.cc:
Auto merged
sql/ha_innodb.cc:
Auto merged
sql/ha_myisam.cc:
Auto merged
sql/handler.h:
Auto merged
sql/item_cmpfunc.cc:
Auto merged
sql/item_strfunc.cc:
Auto merged
sql/item_strfunc.h:
Auto merged
sql/lex.h:
Auto merged
sql/log.cc:
Auto merged
sql/log_event.cc:
Auto merged
sql/mysql_priv.h:
Auto merged
sql/mysqld.cc:
Auto merged
sql/net_pkg.cc:
Auto merged
sql/net_serv.cc:
Auto merged
sql/opt_range.cc:
Auto merged
sql/set_var.h:
Auto merged
sql/slave.cc:
Auto merged
sql/sql_base.cc:
Auto merged
sql/sql_class.h:
Auto merged
sql/sql_insert.cc:
Auto merged
sql/sql_lex.cc:
Auto merged
sql/sql_lex.h:
Auto merged
sql/sql_load.cc:
Auto merged
sql/share/english/errmsg.txt:
Auto merged
sql/sql_table.cc:
Auto merged
sql/sql_udf.cc:
Auto merged
sql/sql_union.cc:
Auto merged
sql/unireg.h:
Auto merged
sql/sql_cache.cc:
Code cleanup (removed ifdef)
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 224 |
1 files changed, 166 insertions, 58 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index bca7b79c132..a71f555cdd7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -74,7 +74,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) } error=mysql_rm_table_part2(thd,tables,if_exists,0); - err: + err: pthread_mutex_unlock(&LOCK_open); VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh @@ -85,7 +85,7 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists) if (error) DBUG_RETURN(-1); - send_ok(&thd->net); + send_ok(thd); DBUG_RETURN(0); } @@ -174,7 +174,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, { if (wrong_tables.length()) wrong_tables.append(','); - wrong_tables.append(String(table->real_name)); + wrong_tables.append(String(table->real_name,default_charset_info)); } } if (some_tables_deleted) @@ -227,7 +227,6 @@ int quick_rm_table(enum db_type base,const char *db, PRIMARY keys are prioritized. */ - static int sort_keys(KEY *a, KEY *b) { if (a->flags & HA_NOSAME) @@ -291,7 +290,8 @@ static int sort_keys(KEY *a, KEY *b) int mysql_create_table(THD *thd,const char *db, const char *table_name, HA_CREATE_INFO *create_info, List<create_field> &fields, - List<Key> &keys,bool tmp_table,bool no_log) + List<Key> &keys,bool tmp_table,bool no_log, + uint select_field_count) { char path[FN_REFLEN]; const char *key_name; @@ -299,14 +299,15 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, int error= -1; uint db_options,field,null_fields,blob_columns; ulong pos; - KEY *key_info,*key_info_buffer; + KEY *key_info,*key_info_buffer; KEY_PART_INFO *key_part_info; int auto_increment=0; handler *file; + int field_no,dup_no; DBUG_ENTER("mysql_create_table"); /* - ** Check for duplicate fields and check type of table to create + Check for duplicate fields and check type of table to create */ if (!fields.elements) @@ -315,6 +316,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } List_iterator<create_field> it(fields),it2(fields); + int select_field_pos=fields.elements - select_field_count; null_fields=blob_columns=0; db_options=create_info->table_options; if (create_info->row_type == ROW_TYPE_DYNAMIC) @@ -328,10 +330,9 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } - /* Don't pack keys in old tables if the user has requested this */ - - while ((sql_field=it++)) + for (field_no=0; (sql_field=it++) ; field_no++) { + /* Don't pack keys in old tables if the user has requested this */ if ((sql_field->flags & BLOB_FLAG) || sql_field->sql_type == FIELD_TYPE_VAR_STRING && create_info->row_type != ROW_TYPE_FIXED) @@ -340,12 +341,36 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, } if (!(sql_field->flags & NOT_NULL_FLAG)) null_fields++; - while ((dup_field=it2++) != sql_field) + + /* Check if we have used the same field name before */ + for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++) { - if (my_strcasecmp(sql_field->field_name, dup_field->field_name) == 0) + if (my_strcasecmp(system_charset_info, + sql_field->field_name, + dup_field->field_name) == 0) { - my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name); - DBUG_RETURN(-1); + /* + If this was a CREATE ... SELECT statement, accept a field + redefinition if we are changing a field in the SELECT part + */ + if (field_no < select_field_pos || dup_no >= select_field_pos) + { + my_error(ER_DUP_FIELDNAME,MYF(0),sql_field->field_name); + DBUG_RETURN(-1); + } + else + { + /* Field redefined */ + sql_field->length= dup_field->length; + sql_field->decimals= dup_field->decimals; + sql_field->flags= dup_field->flags; + sql_field->pack_length= dup_field->pack_length; + sql_field->unireg_check= dup_field->unireg_check; + sql_field->sql_type= dup_field->sql_type; + it2.remove(); // Remove first (create) definition + select_field_pos--; + break; + } } } it2.rewind(); @@ -413,6 +438,11 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, sql_field->offset= pos; if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER) auto_increment++; + if(!sql_field->charset) + sql_field->charset = create_info->table_charset ? + create_info->table_charset : + thd->db_charset? thd->db_charset : + default_charset_info; pos+=sql_field->pack_length; } if (auto_increment > 1) @@ -436,35 +466,50 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, /* Create keys */ List_iterator<Key> key_iterator(keys); - uint key_parts=0,key_count=keys.elements; + uint key_parts=0, key_count=0, fk_key_count=0; List<Key> keys_in_order; // Add new keys here bool primary_key=0,unique_key=0; Key *key; uint tmp, key_number; - tmp=min(file->max_keys(), MAX_KEY); - if (key_count > tmp) - { - my_error(ER_TOO_MANY_KEYS,MYF(0),tmp); - DBUG_RETURN(-1); - } /* Calculate number of key segements */ while ((key=key_iterator++)) { + if (key->type == Key::FOREIGN_KEY) + { + fk_key_count++; + foreign_key *fk_key= (foreign_key*) key; + if (fk_key->ref_columns.elements && + fk_key->ref_columns.elements != fk_key->columns.elements) + { + my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name : + "foreign key without name", + ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF)); + DBUG_RETURN(-1); + } + continue; + } + key_count++; tmp=max(file->max_key_parts(),MAX_REF_PARTS); if (key->columns.elements > tmp) { my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp); DBUG_RETURN(-1); } - if (key->name() && strlen(key->name()) > NAME_LEN) + if (key->name && strlen(key->name) > NAME_LEN) { - my_error(ER_TOO_LONG_IDENT, MYF(0), key->name()); + my_error(ER_TOO_LONG_IDENT, MYF(0), key->name); DBUG_RETURN(-1); } key_parts+=key->columns.elements; } + tmp=min(file->max_keys(), MAX_KEY); + if (key_count > tmp) + { + my_error(ER_TOO_MANY_KEYS,MYF(0),tmp); + DBUG_RETURN(-1); + } key_info_buffer=key_info=(KEY*) sql_calloc(sizeof(KEY)*key_count); key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts); @@ -478,8 +523,23 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, uint key_length=0; key_part_spec *column; - key_info->flags= (key->type == Key::MULTIPLE) ? 0 : - (key->type == Key::FULLTEXT) ? HA_FULLTEXT : HA_NOSAME; + switch(key->type){ + case Key::MULTIPLE: + key_info->flags = 0; + break; + case Key::FULLTEXT: + key_info->flags = HA_FULLTEXT; + break; + case Key::SPATIAL: + key_info->flags = HA_SPATIAL; + break; + case Key::FOREIGN_KEY: + key_number--; // Skip this key + continue; + default: + key_info->flags = HA_NOSAME; + } + key_info->key_parts=(uint8) key->columns.elements; key_info->key_part=key_part_info; key_info->usable_key_parts= key_number; @@ -494,14 +554,42 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_RETURN(-1); } } - + /* + Make SPATIAL to be RTREE by default + SPATIAL only on BLOB or at least BINARY, this + actually should be replaced by special GEOM type + in near future when new frm file is ready + checking for proper key parts number: + */ + + if (key_info->flags == HA_SPATIAL) + { + if (key_info->key_parts != 1) + { + my_printf_error(ER_WRONG_ARGUMENTS, + ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX"); + DBUG_RETURN(-1); + } + } + else if (key_info->algorithm == HA_KEY_ALG_RTREE) + { + if ((key_info->key_parts & 1) == 1) + { + my_printf_error(ER_WRONG_ARGUMENTS, + ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX"); + DBUG_RETURN(-1); + } + } + List_iterator<key_part_spec> cols(key->columns); for (uint column_nr=0 ; (column=cols++) ; column_nr++) { it.rewind(); field=0; while ((sql_field=it++) && - my_strcasecmp(column->field_name,sql_field->field_name)) + my_strcasecmp(system_charset_info, + column->field_name, + sql_field->field_name)) field++; if (!sql_field) { @@ -522,6 +610,14 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, { if (key->type == Key::FULLTEXT) column->length=1; /* ft-code ignores it anyway :-) */ + else if (key->type == Key::SPATIAL) + { + /* + BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case + Lately we'll extend this code to support more dimensions + */ + column->length=4*sizeof(double); + } else { my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH, @@ -613,7 +709,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, key_name=primary_key_name; primary_key=1; } - else if (!(key_name = key->name())) + else if (!(key_name = key->name)) key_name=make_unique_key_name(sql_field->field_name, key_info_buffer,key_info); if (check_if_keyname_exists(key_name,key_info_buffer,key_info)) @@ -684,7 +780,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, create_info->create_statement = thd->query; create_info->table_options=db_options; - if (rea_create_table(path, create_info, fields, key_count, + if (rea_create_table(thd, path, create_info, fields, key_count, key_info_buffer)) { /* my_error(ER_CANT_CREATE_TABLE,MYF(0),table_name,my_errno); */ @@ -724,7 +820,7 @@ static bool check_if_keyname_exists(const char *name, KEY *start, KEY *end) { for (KEY *key=start ; key != end ; key++) - if (!my_strcasecmp(name,key->name)) + if (!my_strcasecmp(system_charset_info,name,key->name)) return 1; return 0; } @@ -760,6 +856,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, TABLE tmp_table; // Used during 'create_field()' TABLE *table; tmp_table.table_name=0; + uint select_field_count= items->elements; DBUG_ENTER("create_table_from_items"); /* Add selected items to field list */ @@ -797,7 +894,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, /* create and lock table */ /* QQ: This should be done atomic ! */ if (mysql_create_table(thd,db,name,create_info,*extra_fields, - *keys,0,1)) // no logging + *keys,0,1,select_field_count)) // no logging DBUG_RETURN(0); if (!(table=open_table(thd,db,name,name,(bool*) 0))) { @@ -1206,7 +1303,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, goto err; } - send_eof(&thd->net); + send_eof(thd); DBUG_RETURN(0); err: close_thread_tables(thd); // Shouldn't be needed @@ -1325,9 +1422,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, strmov(new_name_buff,new_name); fn_same(new_name_buff,table_name,3); if (lower_case_table_names) - casedn_str(new_name); + my_casedn_str(system_charset_info,new_name); if ((lower_case_table_names && - !my_strcasecmp(new_name_buff,table_name)) || + !my_strcasecmp(system_charset_info, new_name_buff,table_name)) || (!lower_case_table_names && !strcmp(new_name_buff,table_name))) new_name=table_name; // No. Make later check easier @@ -1411,7 +1508,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, Query_log_event qinfo(thd, thd->query, thd->query_length); mysql_bin_log.write(&qinfo); } - send_ok(&thd->net); + send_ok(thd); } DBUG_RETURN(error); } @@ -1425,7 +1522,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, List<Key> key_list; // Add new keys here /* - ** First collect all fields from table which isn't in drop_list + First collect all fields from table which isn't in drop_list */ create_field *def; @@ -1438,7 +1535,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, while ((drop=drop_it++)) { if (drop->type == Alter_drop::COLUMN && - !my_strcasecmp(field->field_name, drop->name)) + !my_strcasecmp(system_charset_info,field->field_name, drop->name)) { /* Reset auto_increment value if it was dropped */ if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER && @@ -1459,7 +1556,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, def_it.rewind(); while ((def=def_it++)) { - if (def->change && !my_strcasecmp(field->field_name, def->change)) + if (def->change && + !my_strcasecmp(system_charset_info,field->field_name, def->change)) break; } if (def) @@ -1483,7 +1581,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, Alter_column *alter; while ((alter=alter_it++)) { - if (!my_strcasecmp(field->field_name, alter->name)) + if (!my_strcasecmp(system_charset_info,field->field_name, alter->name)) break; } if (alter) @@ -1517,7 +1615,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, find_it.rewind(); while ((find=find_it++)) // Add new columns { - if (!my_strcasecmp(def->after, find->field_name)) + if (!my_strcasecmp(system_charset_info,def->after, find->field_name)) break; } if (!find) @@ -1540,8 +1638,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, } /* - ** Collect all keys which isn't in drop list. Add only those - ** for which some fields exists. + Collect all keys which isn't in drop list. Add only those + for which some fields exists. */ List_iterator<Key> key_it(keys); @@ -1563,7 +1661,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, while ((drop=drop_it++)) { if (drop->type == Alter_drop::KEY && - !my_strcasecmp(key_name, drop->name)) + !my_strcasecmp(system_charset_info,key_name, drop->name)) break; } if (drop) @@ -1585,11 +1683,13 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, { if (cfield->change) { - if (!my_strcasecmp(key_part_name, cfield->change)) + if (!my_strcasecmp(system_charset_info, key_part_name, + cfield->change)) break; } - else if (!my_strcasecmp(key_part_name, cfield->field_name)) - break; + else if (!my_strcasecmp(system_charset_info, + key_part_name, cfield->field_name)) + break; } if (!cfield) continue; // Field is removed @@ -1606,18 +1706,24 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, key_part_length)); } if (key_parts.elements) - key_list.push_back(new Key(key_info->flags & HA_NOSAME ? - (!my_strcasecmp(key_name, "PRIMARY") ? + key_list.push_back(new Key(key_info->flags & HA_SPATIAL ? Key::SPATIAL : + (key_info->flags & HA_NOSAME ? + (!my_strcasecmp(system_charset_info, + key_name, "PRIMARY") ? Key::PRIMARY : Key::UNIQUE) : - (key_info->flags & HA_FULLTEXT ? - Key::FULLTEXT : Key::MULTIPLE), - key_name,key_parts)); + (key_info->flags & HA_FULLTEXT ? + Key::FULLTEXT : Key::MULTIPLE)), + key_name, + key_info->algorithm, + key_parts)); } - key_it.rewind(); { Key *key; while ((key=key_it++)) // Add new keys - key_list.push_back(key); + { + if (key->type != Key::FOREIGN_KEY) + key_list.push_back(key); + } } if (drop_list.elements) @@ -1645,6 +1751,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, create_info->max_rows=table->max_rows; if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH)) create_info->avg_row_length=table->avg_row_length; + if (!(used_fields & HA_CREATE_USED_CHARSET)) + create_info->table_charset=table->table_charset; table->file->update_create_info(create_info); if ((create_info->table_options & @@ -1712,7 +1820,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, if ((error=mysql_create_table(thd, new_db, tmp_name, create_info, - create_list,key_list,1,1))) // no logging + create_list,key_list,1,1,0))) // no logging DBUG_RETURN(error); if (table->tmp_table) @@ -1789,9 +1897,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, goto err; } /* - ** Data is copied. Now we rename the old table to a temp name, - ** rename the new one to the old name, remove all entries from the old table - ** from the cash, free all locks, close the old table and remove it. + Data is copied. Now we rename the old table to a temp name, + rename the new one to the old name, remove all entries from the old table + from the cash, free all locks, close the old table and remove it. */ thd->proc_info="rename result table"; @@ -1928,7 +2036,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, end_temporary: sprintf(tmp_name,ER(ER_INSERT_INFO),(ulong) (copied+deleted), (ulong) deleted, thd->cuted_fields); - send_ok(&thd->net,copied+deleted,0L,tmp_name); + send_ok(thd,copied+deleted,0L,tmp_name); thd->some_tables_deleted=0; DBUG_RETURN(0); |