00001 /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; either version 2 of the License, or 00006 (at your option) any later version. 00007 00008 This program is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 GNU General Public License for more details. 00012 00013 You should have received a copy of the GNU General Public License 00014 along with this program; if not, write to the Free Software 00015 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 00016 00017 00018 /* Some general useful functions */ 00019 00020 #include "mysql_priv.h" 00021 #include "sql_trigger.h" 00022 #include <m_ctype.h> 00023 #include "md5.h" 00024 00025 /* Functions defined in this file */ 00026 00027 void open_table_error(TABLE_SHARE *share, int error, int db_errno, 00028 myf errortype, int errarg); 00029 static int open_binary_frm(THD *thd, TABLE_SHARE *share, 00030 uchar *head, File file); 00031 static void fix_type_pointers(const char ***array, TYPELIB *point_to_type, 00032 uint types, char **names); 00033 static uint find_field(Field **fields, uint start, uint length); 00034 00035 00036 /* Get column name from column hash */ 00037 00038 static byte *get_field_name(Field **buff, uint *length, 00039 my_bool not_used __attribute__((unused))) 00040 { 00041 *length= (uint) strlen((*buff)->field_name); 00042 return (byte*) (*buff)->field_name; 00043 } 00044 00045 00046 00047 /* 00048 Returns pointer to '.frm' extension of the file name. 00049 00050 SYNOPSIS 00051 fn_rext() 00052 name file name 00053 00054 DESCRIPTION 00055 Checks file name part starting with the rightmost '.' character, 00056 and returns it if it is equal to '.frm'. 00057 00058 TODO 00059 It is a good idea to get rid of this function modifying the code 00060 to garantee that the functions presently calling fn_rext() always 00061 get arguments in the same format: either with '.frm' or without '.frm'. 00062 00063 RETURN VALUES 00064 Pointer to the '.frm' extension. If there is no extension, 00065 or extension is not '.frm', pointer at the end of file name. 00066 */ 00067 00068 char *fn_rext(char *name) 00069 { 00070 char *res= strrchr(name, '.'); 00071 if (res && !strcmp(res, reg_ext)) 00072 return res; 00073 return name + strlen(name); 00074 } 00075 00076 00077 /* 00078 Allocate a setup TABLE_SHARE structure 00079 00080 SYNOPSIS 00081 alloc_table_share() 00082 TABLE_LIST Take database and table name from there 00083 key Table cache key (db \0 table_name \0...) 00084 key_length Length of key 00085 00086 RETURN 00087 0 Error (out of memory) 00088 # Share 00089 */ 00090 00091 TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, char *key, 00092 uint key_length) 00093 { 00094 MEM_ROOT mem_root; 00095 TABLE_SHARE *share; 00096 char *key_buff, *path_buff; 00097 char path[FN_REFLEN]; 00098 uint path_length; 00099 DBUG_ENTER("alloc_table_share"); 00100 DBUG_PRINT("enter", ("table: '%s'.'%s'", 00101 table_list->db, table_list->table_name)); 00102 00103 path_length= build_table_filename(path, sizeof(path) - 1, 00104 table_list->db, 00105 table_list->table_name, "", 0); 00106 init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); 00107 if (multi_alloc_root(&mem_root, 00108 &share, sizeof(*share), 00109 &key_buff, key_length, 00110 &path_buff, path_length + 1, 00111 NULL)) 00112 { 00113 bzero((char*) share, sizeof(*share)); 00114 00115 share->set_table_cache_key(key_buff, key, key_length); 00116 00117 share->path.str= path_buff; 00118 share->path.length= path_length; 00119 strmov(share->path.str, path); 00120 share->normalized_path.str= share->path.str; 00121 share->normalized_path.length= path_length; 00122 00123 share->version= refresh_version; 00124 share->flush_version= flush_version; 00125 00126 #ifdef HAVE_ROW_BASED_REPLICATION 00127 /* 00128 This constant is used to mark that no table map version has been 00129 assigned. No arithmetic is done on the value: it will be 00130 overwritten with a value taken from MYSQL_BIN_LOG. 00131 */ 00132 share->table_map_version= ~(ulonglong)0; 00133 00134 /* 00135 Since alloc_table_share() can be called without any locking (for 00136 example, ha_create_table... functions), we do not assign a table 00137 map id here. Instead we assign a value that is not used 00138 elsewhere, and then assign a table map id inside open_table() 00139 under the protection of the LOCK_open mutex. 00140 */ 00141 share->table_map_id= ~0UL; 00142 share->cached_row_logging_check= -1; 00143 00144 #endif 00145 00146 memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root)); 00147 pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST); 00148 pthread_cond_init(&share->cond, NULL); 00149 } 00150 DBUG_RETURN(share); 00151 } 00152 00153 00154 /* 00155 Initialize share for temporary tables 00156 00157 SYNOPSIS 00158 init_tmp_table_share() 00159 share Share to fill 00160 key Table_cache_key, as generated from create_table_def_key. 00161 must start with db name. 00162 key_length Length of key 00163 table_name Table name 00164 path Path to file (possible in lower case) without .frm 00165 00166 NOTES 00167 This is different from alloc_table_share() because temporary tables 00168 don't have to be shared between threads or put into the table def 00169 cache, so we can do some things notable simpler and faster 00170 00171 If table is not put in thd->temporary_tables (happens only when 00172 one uses OPEN TEMPORARY) then one can specify 'db' as key and 00173 use key_length= 0 as neither table_cache_key or key_length will be used). 00174 */ 00175 00176 void init_tmp_table_share(TABLE_SHARE *share, const char *key, 00177 uint key_length, const char *table_name, 00178 const char *path) 00179 { 00180 DBUG_ENTER("init_tmp_table_share"); 00181 DBUG_PRINT("enter", ("table: '%s'.'%s'", key, table_name)); 00182 00183 bzero((char*) share, sizeof(*share)); 00184 init_sql_alloc(&share->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); 00185 share->tmp_table= INTERNAL_TMP_TABLE; 00186 share->db.str= (char*) key; 00187 share->db.length= strlen(key); 00188 share->table_cache_key.str= (char*) key; 00189 share->table_cache_key.length= key_length; 00190 share->table_name.str= (char*) table_name; 00191 share->table_name.length= strlen(table_name); 00192 share->path.str= (char*) path; 00193 share->normalized_path.str= (char*) path; 00194 share->path.length= share->normalized_path.length= strlen(path); 00195 share->frm_version= FRM_VER_TRUE_VARCHAR; 00196 00197 #ifdef HAVE_ROW_BASED_REPLICATION 00198 /* 00199 Temporary tables are not replicated, but we set up these fields 00200 anyway to be able to catch errors. 00201 */ 00202 share->table_map_version= ~(ulonglong)0; 00203 share->table_map_id= ~0UL; 00204 share->cached_row_logging_check= -1; 00205 #endif 00206 00207 DBUG_VOID_RETURN; 00208 } 00209 00210 00211 /* 00212 Free table share and memory used by it 00213 00214 SYNOPSIS 00215 free_table_share() 00216 share Table share 00217 00218 NOTES 00219 share->mutex must be locked when we come here if it's not a temp table 00220 */ 00221 00222 void free_table_share(TABLE_SHARE *share) 00223 { 00224 MEM_ROOT mem_root; 00225 DBUG_ENTER("free_table_share"); 00226 DBUG_PRINT("enter", ("table: %s.%s", share->db.str, share->table_name.str)); 00227 DBUG_ASSERT(share->ref_count == 0); 00228 00229 /* 00230 If someone is waiting for this to be deleted, inform it about this. 00231 Don't do a delete until we know that no one is refering to this anymore. 00232 */ 00233 if (share->tmp_table == NO_TMP_TABLE) 00234 { 00235 /* share->mutex is locked in release_table_share() */ 00236 while (share->waiting_on_cond) 00237 { 00238 pthread_cond_broadcast(&share->cond); 00239 pthread_cond_wait(&share->cond, &share->mutex); 00240 } 00241 /* No thread refers to this anymore */ 00242 pthread_mutex_unlock(&share->mutex); 00243 pthread_mutex_destroy(&share->mutex); 00244 pthread_cond_destroy(&share->cond); 00245 } 00246 hash_free(&share->name_hash); 00247 00248 /* We must copy mem_root from share because share is allocated through it */ 00249 memcpy((char*) &mem_root, (char*) &share->mem_root, sizeof(mem_root)); 00250 free_root(&mem_root, MYF(0)); // Free's share 00251 DBUG_VOID_RETURN; 00252 } 00253 00254 00255 /* 00256 Read table definition from a binary / text based .frm file 00257 00258 SYNOPSIS 00259 open_table_def() 00260 thd Thread handler 00261 share Fill this with table definition 00262 db_flags Bit mask of the following flags: OPEN_VIEW 00263 00264 NOTES 00265 This function is called when the table definition is not cached in 00266 table_def_cache 00267 The data is returned in 'share', which is alloced by 00268 alloc_table_share().. The code assumes that share is initialized. 00269 00270 RETURN VALUES 00271 0 ok 00272 1 Error (see open_table_error) 00273 2 Error (see open_table_error) 00274 3 Wrong data in .frm file 00275 4 Error (see open_table_error) 00276 5 Error (see open_table_error: charset unavailable) 00277 6 Unknown .frm version 00278 */ 00279 00280 int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) 00281 { 00282 int error, table_type; 00283 bool error_given; 00284 File file; 00285 uchar head[288], *disk_buff; 00286 char path[FN_REFLEN]; 00287 MEM_ROOT **root_ptr, *old_root; 00288 DBUG_ENTER("open_table_def"); 00289 DBUG_PRINT("enter", ("table: '%s'.'%s' path: '%s'", share->db.str, 00290 share->table_name.str, share->normalized_path.str)); 00291 00292 error= 1; 00293 error_given= 0; 00294 disk_buff= NULL; 00295 00296 strxmov(path, share->normalized_path.str, reg_ext, NullS); 00297 if ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0) 00298 { 00299 if (strchr(share->table_name.str, '@')) 00300 goto err_not_open; 00301 00302 /* Try unecoded 5.0 name */ 00303 uint length; 00304 strxnmov(path, sizeof(path)-1, 00305 mysql_data_home, "/", share->db.str, "/", 00306 share->table_name.str, reg_ext, NullS); 00307 length= unpack_filename(path, path) - reg_ext_length; 00308 /* 00309 The following is a safety test and should never fail 00310 as the old file name should never be longer than the new one. 00311 */ 00312 DBUG_ASSERT(length <= share->normalized_path.length); 00313 /* 00314 If the old and the new names have the same length, 00315 then table name does not have tricky characters, 00316 so no need to check the old file name. 00317 */ 00318 if (length == share->normalized_path.length || 00319 ((file= my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)) 00320 goto err_not_open; 00321 00322 /* Unencoded 5.0 table name found */ 00323 path[length]= '\0'; // Remove .frm extension 00324 strmov(share->normalized_path.str, path); 00325 share->normalized_path.length= length; 00326 } 00327 00328 error= 4; 00329 if (my_read(file,(byte*) head, 64, MYF(MY_NABP))) 00330 goto err; 00331 00332 if (head[0] == (uchar) 254 && head[1] == 1) 00333 { 00334 if (head[2] == FRM_VER || head[2] == FRM_VER+1 || 00335 (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4)) 00336 table_type= 1; 00337 else 00338 { 00339 error= 6; // Unkown .frm version 00340 goto err; 00341 } 00342 } 00343 else if (memcmp(head, STRING_WITH_LEN("TYPE=")) == 0) 00344 { 00345 error= 5; 00346 if (memcmp(head+5,"VIEW",4) == 0) 00347 { 00348 share->is_view= 1; 00349 if (db_flags & OPEN_VIEW) 00350 error= 0; 00351 } 00352 goto err; 00353 } 00354 else 00355 goto err; 00356 00357 /* No handling of text based files yet */ 00358 if (table_type == 1) 00359 { 00360 root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); 00361 old_root= *root_ptr; 00362 *root_ptr= &share->mem_root; 00363 error= open_binary_frm(thd, share, head, file); 00364 *root_ptr= old_root; 00365 00366 if (share->db.length == 5 && 00367 !my_strcasecmp(system_charset_info, share->db.str, "mysql")) 00368 { 00369 /* 00370 We can't mark all tables in 'mysql' database as system since we don't 00371 allow to lock such tables for writing with any other tables (even with 00372 other system tables) and some privilege tables need this. 00373 */ 00374 if (!my_strcasecmp(system_charset_info, share->table_name.str, "proc")) 00375 share->system_table= 1; 00376 else 00377 { 00378 if (!my_strcasecmp(system_charset_info, share->table_name.str, 00379 "general_log")) 00380 share->log_table= QUERY_LOG_GENERAL; 00381 else 00382 if (!my_strcasecmp(system_charset_info, share->table_name.str, 00383 "slow_log")) 00384 share->log_table= QUERY_LOG_SLOW; 00385 } 00386 } 00387 error_given= 1; 00388 } 00389 00390 if (!error) 00391 thd->status_var.opened_shares++; 00392 00393 err: 00394 my_close(file, MYF(MY_WME)); 00395 00396 err_not_open: 00397 if (error && !error_given) 00398 { 00399 share->error= error; 00400 open_table_error(share, error, (share->open_errno= my_errno), 0); 00401 } 00402 00403 DBUG_RETURN(error); 00404 } 00405 00406 00407 /* 00408 Read data from a binary .frm file from MySQL 3.23 - 5.0 into TABLE_SHARE 00409 */ 00410 00411 static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, 00412 File file) 00413 { 00414 int error, errarg= 0; 00415 uint new_frm_ver, field_pack_length, new_field_pack_flag; 00416 uint interval_count, interval_parts, read_length, int_length; 00417 uint db_create_options, keys, key_parts, n_length; 00418 uint key_info_length, com_length, null_bit_pos; 00419 uint extra_rec_buf_length; 00420 uint i,j; 00421 bool use_hash; 00422 char *keynames, *record, *names, *comment_pos; 00423 uchar *disk_buff, *strpos, *null_flags, *null_pos; 00424 ulong pos, record_offset, *rec_per_key, rec_buff_length; 00425 handler *handler_file= 0; 00426 KEY *keyinfo; 00427 KEY_PART_INFO *key_part; 00428 SQL_CRYPT *crypted=0; 00429 Field **field_ptr, *reg_field; 00430 const char **interval_array; 00431 enum legacy_db_type legacy_db_type; 00432 my_bitmap_map *bitmaps; 00433 DBUG_ENTER("open_binary_frm"); 00434 00435 new_field_pack_flag= head[27]; 00436 new_frm_ver= (head[2] - FRM_VER); 00437 field_pack_length= new_frm_ver < 2 ? 11 : 17; 00438 disk_buff= 0; 00439 00440 error= 3; 00441 if (!(pos=get_form_pos(file,head,(TYPELIB*) 0))) 00442 goto err; /* purecov: inspected */ 00443 00444 share->frm_version= head[2]; 00445 /* 00446 Check if .frm file created by MySQL 5.0. In this case we want to 00447 display CHAR fields as CHAR and not as VARCHAR. 00448 We do it this way as we want to keep the old frm version to enable 00449 MySQL 4.1 to read these files. 00450 */ 00451 if (share->frm_version == FRM_VER_TRUE_VARCHAR -1 && head[33] == 5) 00452 share->frm_version= FRM_VER_TRUE_VARCHAR; 00453 00454 #ifdef WITH_PARTITION_STORAGE_ENGINE 00455 if (*(head+61) && 00456 !(share->default_part_db_type= 00457 ha_checktype(thd, (enum legacy_db_type) (uint) *(head+61), 1, 0))) 00458 goto err; 00459 DBUG_PRINT("info", ("default_part_db_type = %u", head[61])); 00460 #endif 00461 legacy_db_type= (enum legacy_db_type) (uint) *(head+3); 00462 share->db_type= ha_checktype(thd, legacy_db_type, 0, 0); 00463 share->db_create_options= db_create_options= uint2korr(head+30); 00464 share->db_options_in_use= share->db_create_options; 00465 share->mysql_version= uint4korr(head+51); 00466 share->null_field_first= 0; 00467 if (!head[32]) // New frm file in 3.23 00468 { 00469 share->avg_row_length= uint4korr(head+34); 00470 share-> row_type= (row_type) head[40]; 00471 share->table_charset= get_charset((uint) head[38],MYF(0)); 00472 share->null_field_first= 1; 00473 } 00474 if (!share->table_charset) 00475 { 00476 /* unknown charset in head[38] or pre-3.23 frm */ 00477 if (use_mb(default_charset_info)) 00478 { 00479 /* Warn that we may be changing the size of character columns */ 00480 sql_print_warning("'%s' had no or invalid character set, " 00481 "and default character set is multi-byte, " 00482 "so character column sizes may have changed", 00483 share->path); 00484 } 00485 share->table_charset= default_charset_info; 00486 } 00487 share->db_record_offset= 1; 00488 if (db_create_options & HA_OPTION_LONG_BLOB_PTR) 00489 share->blob_ptr_size= portable_sizeof_char_ptr; 00490 /* Set temporarily a good value for db_low_byte_first */ 00491 share->db_low_byte_first= test(legacy_db_type != DB_TYPE_ISAM); 00492 error=4; 00493 share->max_rows= uint4korr(head+18); 00494 share->min_rows= uint4korr(head+22); 00495 00496 /* Read keyinformation */ 00497 key_info_length= (uint) uint2korr(head+28); 00498 VOID(my_seek(file,(ulong) uint2korr(head+6),MY_SEEK_SET,MYF(0))); 00499 if (read_string(file,(gptr*) &disk_buff,key_info_length)) 00500 goto err; /* purecov: inspected */ 00501 if (disk_buff[0] & 0x80) 00502 { 00503 share->keys= keys= (disk_buff[1] << 7) | (disk_buff[0] & 0x7f); 00504 share->key_parts= key_parts= uint2korr(disk_buff+2); 00505 } 00506 else 00507 { 00508 share->keys= keys= disk_buff[0]; 00509 share->key_parts= key_parts= disk_buff[1]; 00510 } 00511 share->keys_for_keyread.init(0); 00512 share->keys_in_use.init(keys); 00513 00514 n_length=keys*sizeof(KEY)+key_parts*sizeof(KEY_PART_INFO); 00515 if (!(keyinfo = (KEY*) alloc_root(&share->mem_root, 00516 n_length + uint2korr(disk_buff+4)))) 00517 goto err; /* purecov: inspected */ 00518 bzero((char*) keyinfo,n_length); 00519 share->key_info= keyinfo; 00520 key_part= my_reinterpret_cast(KEY_PART_INFO*) (keyinfo+keys); 00521 strpos=disk_buff+6; 00522 00523 if (!(rec_per_key= (ulong*) alloc_root(&share->mem_root, 00524 sizeof(ulong*)*key_parts))) 00525 goto err; 00526 00527 for (i=0 ; i < keys ; i++, keyinfo++) 00528 { 00529 keyinfo->table= 0; // Updated in open_frm 00530 if (new_frm_ver >= 3) 00531 { 00532 keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME; 00533 keyinfo->key_length= (uint) uint2korr(strpos+2); 00534 keyinfo->key_parts= (uint) strpos[4]; 00535 keyinfo->algorithm= (enum ha_key_alg) strpos[5]; 00536 keyinfo->block_size= uint2korr(strpos+6); 00537 strpos+=8; 00538 } 00539 else 00540 { 00541 keyinfo->flags= ((uint) strpos[0]) ^ HA_NOSAME; 00542 keyinfo->key_length= (uint) uint2korr(strpos+1); 00543 keyinfo->key_parts= (uint) strpos[3]; 00544 keyinfo->algorithm= HA_KEY_ALG_UNDEF; 00545 strpos+=4; 00546 } 00547 00548 keyinfo->key_part= key_part; 00549 keyinfo->rec_per_key= rec_per_key; 00550 for (j=keyinfo->key_parts ; j-- ; key_part++) 00551 { 00552 *rec_per_key++=0; 00553 key_part->fieldnr= (uint16) (uint2korr(strpos) & FIELD_NR_MASK); 00554 key_part->offset= (uint) uint2korr(strpos+2)-1; 00555 key_part->key_type= (uint) uint2korr(strpos+5); 00556 // key_part->field= (Field*) 0; // Will be fixed later 00557 if (new_frm_ver >= 1) 00558 { 00559 key_part->key_part_flag= *(strpos+4); 00560 key_part->length= (uint) uint2korr(strpos+7); 00561 strpos+=9; 00562 } 00563 else 00564 { 00565 key_part->length= *(strpos+4); 00566 key_part->key_part_flag=0; 00567 if (key_part->length > 128) 00568 { 00569 key_part->length&=127; /* purecov: inspected */ 00570 key_part->key_part_flag=HA_REVERSE_SORT; /* purecov: inspected */ 00571 } 00572 strpos+=7; 00573 } 00574 key_part->store_length=key_part->length; 00575 } 00576 } 00577 keynames=(char*) key_part; 00578 strpos+= (strmov(keynames, (char *) strpos) - keynames)+1; 00579 00580 share->reclength = uint2korr((head+16)); 00581 if (*(head+26) == 1) 00582 share->system= 1; /* one-record-database */ 00583 #ifdef HAVE_CRYPTED_FRM 00584 else if (*(head+26) == 2) 00585 { 00586 crypted= get_crypt_for_frm(); 00587 share->crypted= 1; 00588 } 00589 #endif 00590 00591 record_offset= (ulong) (uint2korr(head+6)+ 00592 ((uint2korr(head+14) == 0xffff ? 00593 uint4korr(head+47) : uint2korr(head+14)))); 00594 00595 if ((n_length= uint4korr(head+55))) 00596 { 00597 /* Read extra data segment */ 00598 char *buff, *next_chunk, *buff_end; 00599 DBUG_PRINT("info", ("extra segment size is %u bytes", n_length)); 00600 if (!(next_chunk= buff= my_malloc(n_length, MYF(MY_WME)))) 00601 goto err; 00602 if (my_pread(file, (byte*)buff, n_length, record_offset + share->reclength, 00603 MYF(MY_NABP))) 00604 { 00605 my_free(buff, MYF(0)); 00606 goto err; 00607 } 00608 share->connect_string.length= uint2korr(buff); 00609 if (! (share->connect_string.str= strmake_root(&share->mem_root, 00610 next_chunk + 2, share->connect_string.length))) 00611 { 00612 my_free(buff, MYF(0)); 00613 goto err; 00614 } 00615 next_chunk+= share->connect_string.length + 2; 00616 buff_end= buff + n_length; 00617 if (next_chunk + 2 < buff_end) 00618 { 00619 uint str_db_type_length= uint2korr(next_chunk); 00620 LEX_STRING name= { next_chunk + 2, str_db_type_length }; 00621 handlerton *tmp_db_type= ha_resolve_by_name(thd, &name); 00622 if (tmp_db_type != NULL) 00623 { 00624 share->db_type= tmp_db_type; 00625 DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", 00626 str_db_type_length, next_chunk + 2, 00627 ha_legacy_type(share->db_type))); 00628 } 00629 #ifdef WITH_PARTITION_STORAGE_ENGINE 00630 else 00631 { 00632 if (!strncmp(next_chunk + 2, "partition", str_db_type_length)) 00633 { 00634 /* Use partition handler */ 00635 share->db_type= &partition_hton; 00636 DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", 00637 str_db_type_length, next_chunk + 2, 00638 ha_legacy_type(share->db_type))); 00639 } 00640 } 00641 #endif 00642 next_chunk+= str_db_type_length + 2; 00643 } 00644 if (next_chunk + 5 < buff_end) 00645 { 00646 uint32 partition_info_len = uint4korr(next_chunk); 00647 #ifdef WITH_PARTITION_STORAGE_ENGINE 00648 if ((share->partition_info_len= partition_info_len)) 00649 { 00650 if (!(share->partition_info= 00651 (uchar*) memdup_root(&share->mem_root, next_chunk + 4, 00652 partition_info_len + 1))) 00653 { 00654 my_free(buff, MYF(0)); 00655 goto err; 00656 } 00657 } 00658 #else 00659 if (partition_info_len) 00660 { 00661 DBUG_PRINT("info", ("WITH_PARTITION_STORAGE_ENGINE is not defined")); 00662 my_free(buff, MYF(0)); 00663 goto err; 00664 } 00665 #endif 00666 next_chunk+= 5 + partition_info_len; 00667 } 00668 #if MYSQL_VERSION_ID < 50200 00669 if (share->mysql_version >= 50106 && share->mysql_version <= 50109) 00670 { 00671 /* 00672 Partition state array was here in version 5.1.6 to 5.1.9, this code 00673 makes it possible to load a 5.1.6 table in later versions. Can most 00674 likely be removed at some point in time. Will only be used for 00675 upgrades within 5.1 series of versions. Upgrade to 5.2 can only be 00676 done from newer 5.1 versions. 00677 */ 00678 next_chunk+= 4; 00679 } 00680 else if (share->mysql_version >= 50110) 00681 #endif 00682 { 00683 /* New auto_partitioned indicator introduced in 5.1.11 */ 00684 #ifdef WITH_PARTITION_STORAGE_ENGINE 00685 share->auto_partitioned= *next_chunk; 00686 #endif 00687 next_chunk++; 00688 } 00689 keyinfo= share->key_info; 00690 for (i= 0; i < keys; i++, keyinfo++) 00691 { 00692 if (keyinfo->flags & HA_USES_PARSER) 00693 { 00694 LEX_STRING parser_name; 00695 if (next_chunk >= buff_end) 00696 { 00697 DBUG_PRINT("error", 00698 ("fulltext key uses parser that is not defined in .frm")); 00699 my_free(buff, MYF(0)); 00700 goto err; 00701 } 00702 parser_name.str= next_chunk; 00703 parser_name.length= strlen(next_chunk); 00704 keyinfo->parser= plugin_lock(&parser_name, MYSQL_FTPARSER_PLUGIN); 00705 if (! keyinfo->parser) 00706 { 00707 my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), parser_name.str); 00708 my_free(buff, MYF(0)); 00709 goto err; 00710 } 00711 } 00712 } 00713 my_free(buff, MYF(0)); 00714 } 00715 share->key_block_size= uint2korr(head+62); 00716 00717 error=4; 00718 extra_rec_buf_length= uint2korr(head+59); 00719 rec_buff_length= ALIGN_SIZE(share->reclength + 1 + extra_rec_buf_length); 00720 share->rec_buff_length= rec_buff_length; 00721 if (!(record= (char *) alloc_root(&share->mem_root, 00722 rec_buff_length))) 00723 goto err; /* purecov: inspected */ 00724 share->default_values= (byte *) record; 00725 if (my_pread(file,(byte*) record, (uint) share->reclength, 00726 record_offset, MYF(MY_NABP))) 00727 goto err; /* purecov: inspected */ 00728 00729 VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0))); 00730 if (my_read(file,(byte*) head,288,MYF(MY_NABP))) 00731 goto err; 00732 #ifdef HAVE_CRYPTED_FRM 00733 if (crypted) 00734 { 00735 crypted->decode((char*) head+256,288-256); 00736 if (sint2korr(head+284) != 0) // Should be 0 00737 goto err; // Wrong password 00738 } 00739 #endif 00740 00741 share->fields= uint2korr(head+258); 00742 pos= uint2korr(head+260); /* Length of all screens */ 00743 n_length= uint2korr(head+268); 00744 interval_count= uint2korr(head+270); 00745 interval_parts= uint2korr(head+272); 00746 int_length= uint2korr(head+274); 00747 share->null_fields= uint2korr(head+282); 00748 com_length= uint2korr(head+284); 00749 share->comment.length= (int) (head[46]); 00750 share->comment.str= strmake_root(&share->mem_root, (char*) head+47, 00751 share->comment.length); 00752 00753 DBUG_PRINT("info",("i_count: %d i_parts: %d index: %d n_length: %d int_length: %d com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length)); 00754 00755 if (!(field_ptr = (Field **) 00756 alloc_root(&share->mem_root, 00757 (uint) ((share->fields+1)*sizeof(Field*)+ 00758 interval_count*sizeof(TYPELIB)+ 00759 (share->fields+interval_parts+ 00760 keys+3)*sizeof(my_string)+ 00761 (n_length+int_length+com_length))))) 00762 goto err; /* purecov: inspected */ 00763 00764 share->field= field_ptr; 00765 read_length=(uint) (share->fields * field_pack_length + 00766 pos+ (uint) (n_length+int_length+com_length)); 00767 if (read_string(file,(gptr*) &disk_buff,read_length)) 00768 goto err; /* purecov: inspected */ 00769 #ifdef HAVE_CRYPTED_FRM 00770 if (crypted) 00771 { 00772 crypted->decode((char*) disk_buff,read_length); 00773 delete crypted; 00774 crypted=0; 00775 } 00776 #endif 00777 strpos= disk_buff+pos; 00778 00779 share->intervals= (TYPELIB*) (field_ptr+share->fields+1); 00780 interval_array= (const char **) (share->intervals+interval_count); 00781 names= (char*) (interval_array+share->fields+interval_parts+keys+3); 00782 if (!interval_count) 00783 share->intervals= 0; // For better debugging 00784 memcpy((char*) names, strpos+(share->fields*field_pack_length), 00785 (uint) (n_length+int_length)); 00786 comment_pos= names+(n_length+int_length); 00787 memcpy(comment_pos, disk_buff+read_length-com_length, com_length); 00788 00789 fix_type_pointers(&interval_array, &share->fieldnames, 1, &names); 00790 fix_type_pointers(&interval_array, share->intervals, interval_count, 00791 &names); 00792 00793 { 00794 /* Set ENUM and SET lengths */ 00795 TYPELIB *interval; 00796 for (interval= share->intervals; 00797 interval < share->intervals + interval_count; 00798 interval++) 00799 { 00800 uint count= (uint) (interval->count + 1) * sizeof(uint); 00801 if (!(interval->type_lengths= (uint *) alloc_root(&share->mem_root, 00802 count))) 00803 goto err; 00804 for (count= 0; count < interval->count; count++) 00805 interval->type_lengths[count]= strlen(interval->type_names[count]); 00806 interval->type_lengths[count]= 0; 00807 } 00808 } 00809 00810 if (keynames) 00811 fix_type_pointers(&interval_array, &share->keynames, 1, &keynames); 00812 00813 /* Allocate handler */ 00814 if (!(handler_file= get_new_handler(share, thd->mem_root, 00815 share->db_type))) 00816 goto err; 00817 00818 record= (char*) share->default_values-1; /* Fieldstart = 1 */ 00819 if (share->null_field_first) 00820 { 00821 null_flags= null_pos= (uchar*) record+1; 00822 null_bit_pos= (db_create_options & HA_OPTION_PACK_RECORD) ? 0 : 1; 00823 /* 00824 null_bytes below is only correct under the condition that 00825 there are no bit fields. Correct values is set below after the 00826 table struct is initialized 00827 */ 00828 share->null_bytes= (share->null_fields + null_bit_pos + 7) / 8; 00829 } 00830 #ifndef WE_WANT_TO_SUPPORT_VERY_OLD_FRM_FILES 00831 else 00832 { 00833 share->null_bytes= (share->null_fields+7)/8; 00834 null_flags= null_pos= (uchar*) (record + 1 +share->reclength - 00835 share->null_bytes); 00836 null_bit_pos= 0; 00837 } 00838 #endif 00839 00840 use_hash= share->fields >= MAX_FIELDS_BEFORE_HASH; 00841 if (use_hash) 00842 use_hash= !hash_init(&share->name_hash, 00843 system_charset_info, 00844 share->fields,0,0, 00845 (hash_get_key) get_field_name,0,0); 00846 00847 for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++) 00848 { 00849 uint pack_flag, interval_nr, unireg_type, recpos, field_length; 00850 enum_field_types field_type; 00851 CHARSET_INFO *charset=NULL; 00852 Field::geometry_type geom_type= Field::GEOM_GEOMETRY; 00853 LEX_STRING comment; 00854 00855 if (new_frm_ver >= 3) 00856 { 00857 /* new frm file in 4.1 */ 00858 field_length= uint2korr(strpos+3); 00859 recpos= uint3korr(strpos+5); 00860 pack_flag= uint2korr(strpos+8); 00861 unireg_type= (uint) strpos[10]; 00862 interval_nr= (uint) strpos[12]; 00863 uint comment_length=uint2korr(strpos+15); 00864 field_type=(enum_field_types) (uint) strpos[13]; 00865 00866 /* charset and geometry_type share the same byte in frm */ 00867 if (field_type == FIELD_TYPE_GEOMETRY) 00868 { 00869 #ifdef HAVE_SPATIAL 00870 geom_type= (Field::geometry_type) strpos[14]; 00871 charset= &my_charset_bin; 00872 #else 00873 error= 4; // unsupported field type 00874 goto err; 00875 #endif 00876 } 00877 else 00878 { 00879 if (!strpos[14]) 00880 charset= &my_charset_bin; 00881 else if (!(charset=get_charset((uint) strpos[14], MYF(0)))) 00882 { 00883 error= 5; // Unknown or unavailable charset 00884 errarg= (int) strpos[14]; 00885 goto err; 00886 } 00887 } 00888 if (!comment_length) 00889 { 00890 comment.str= (char*) ""; 00891 comment.length=0; 00892 } 00893 else 00894 { 00895 comment.str= (char*) comment_pos; 00896 comment.length= comment_length; 00897 comment_pos+= comment_length; 00898 } 00899 } 00900 else 00901 { 00902 field_length= (uint) strpos[3]; 00903 recpos= uint2korr(strpos+4), 00904 pack_flag= uint2korr(strpos+6); 00905 pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files 00906 unireg_type= (uint) strpos[8]; 00907 interval_nr= (uint) strpos[10]; 00908 00909 /* old frm file */ 00910 field_type= (enum_field_types) f_packtype(pack_flag); 00911 if (f_is_binary(pack_flag)) 00912 { 00913 /* 00914 Try to choose the best 4.1 type: 00915 - for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY" 00916 try to find a binary collation for character set. 00917 - for other types (e.g. BLOB) just use my_charset_bin. 00918 */ 00919 if (!f_is_blob(pack_flag)) 00920 { 00921 // 3.23 or 4.0 string 00922 if (!(charset= get_charset_by_csname(share->table_charset->csname, 00923 MY_CS_BINSORT, MYF(0)))) 00924 charset= &my_charset_bin; 00925 } 00926 else 00927 charset= &my_charset_bin; 00928 } 00929 else 00930 charset= share->table_charset; 00931 bzero((char*) &comment, sizeof(comment)); 00932 } 00933 00934 if (interval_nr && charset->mbminlen > 1) 00935 { 00936 /* Unescape UCS2 intervals from HEX notation */ 00937 TYPELIB *interval= share->intervals + interval_nr - 1; 00938 unhex_type2(interval); 00939 } 00940 00941 #ifndef TO_BE_DELETED_ON_PRODUCTION 00942 if (field_type == FIELD_TYPE_NEWDECIMAL && !share->mysql_version) 00943 { 00944 /* 00945 Fix pack length of old decimal values from 5.0.3 -> 5.0.4 00946 The difference is that in the old version we stored precision 00947 in the .frm table while we now store the display_length 00948 */ 00949 uint decimals= f_decimals(pack_flag); 00950 field_length= my_decimal_precision_to_length(field_length, 00951 decimals, 00952 f_is_dec(pack_flag) == 0); 00953 sql_print_error("Found incompatible DECIMAL field '%s' in %s; " 00954 "Please do \"ALTER TABLE '%s' FORCE\" to fix it!", 00955 share->fieldnames.type_names[i], share->table_name.str, 00956 share->table_name.str); 00957 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, 00958 ER_CRASHED_ON_USAGE, 00959 "Found incompatible DECIMAL field '%s' in %s; " 00960 "Please do \"ALTER TABLE '%s' FORCE\" to fix it!", 00961 share->fieldnames.type_names[i], 00962 share->table_name.str, 00963 share->table_name.str); 00964 share->crashed= 1; // Marker for CHECK TABLE 00965 } 00966 #endif 00967 00968 *field_ptr= reg_field= 00969 make_field(share, record+recpos, 00970 (uint32) field_length, 00971 null_pos, null_bit_pos, 00972 pack_flag, 00973 field_type, 00974 charset, 00975 geom_type, 00976 (Field::utype) MTYP_TYPENR(unireg_type), 00977 (interval_nr ? 00978 share->intervals+interval_nr-1 : 00979 (TYPELIB*) 0), 00980 share->fieldnames.type_names[i]); 00981 if (!reg_field) // Not supported field type 00982 { 00983 error= 4; 00984 goto err; /* purecov: inspected */ 00985 } 00986 00987 reg_field->field_index= i; 00988 reg_field->comment=comment; 00989 if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag)) 00990 { 00991 if ((null_bit_pos+= field_length & 7) > 7) 00992 { 00993 null_pos++; 00994 null_bit_pos-= 8; 00995 } 00996 } 00997 if (!(reg_field->flags & NOT_NULL_FLAG)) 00998 { 00999 if (!(null_bit_pos= (null_bit_pos + 1) & 7)) 01000 null_pos++; 01001 } 01002 if (f_no_default(pack_flag)) 01003 reg_field->flags|= NO_DEFAULT_VALUE_FLAG; 01004 01005 if (reg_field->unireg_check == Field::NEXT_NUMBER) 01006 share->found_next_number_field= field_ptr; 01007 if (share->timestamp_field == reg_field) 01008 share->timestamp_field_offset= i; 01009 01010 if (use_hash) 01011 (void) my_hash_insert(&share->name_hash, 01012 (byte*) field_ptr); // never fail 01013 } 01014 *field_ptr=0; // End marker 01015 01016 /* Fix key->name and key_part->field */ 01017 if (key_parts) 01018 { 01019 uint primary_key=(uint) (find_type((char*) primary_key_name, 01020 &share->keynames, 3) - 1); 01021 uint ha_option= handler_file->ha_table_flags(); 01022 keyinfo= share->key_info; 01023 key_part= keyinfo->key_part; 01024 01025 for (uint key=0 ; key < share->keys ; key++,keyinfo++) 01026 { 01027 uint usable_parts= 0; 01028 keyinfo->name=(char*) share->keynames.type_names[key]; 01029 /* Fix fulltext keys for old .frm files */ 01030 if (share->key_info[key].flags & HA_FULLTEXT) 01031 share->key_info[key].algorithm= HA_KEY_ALG_FULLTEXT; 01032 01033 if (primary_key >= MAX_KEY && (keyinfo->flags & HA_NOSAME)) 01034 { 01035 /* 01036 If the UNIQUE key doesn't have NULL columns and is not a part key 01037 declare this as a primary key. 01038 */ 01039 primary_key=key; 01040 for (i=0 ; i < keyinfo->key_parts ;i++) 01041 { 01042 uint fieldnr= key_part[i].fieldnr; 01043 if (!fieldnr || 01044 share->field[fieldnr-1]->null_ptr || 01045 share->field[fieldnr-1]->key_length() != 01046 key_part[i].length) 01047 { 01048 primary_key=MAX_KEY; // Can't be used 01049 break; 01050 } 01051 } 01052 } 01053 01054 for (i=0 ; i < keyinfo->key_parts ; key_part++,i++) 01055 { 01056 Field *field; 01057 if (new_field_pack_flag <= 1) 01058 key_part->fieldnr= (uint16) find_field(share->field, 01059 (uint) key_part->offset, 01060 (uint) key_part->length); 01061 if (!key_part->fieldnr) 01062 { 01063 error= 4; // Wrong file 01064 goto err; 01065 } 01066 field= key_part->field= share->field[key_part->fieldnr-1]; 01067 if (field->null_ptr) 01068 { 01069 key_part->null_offset=(uint) ((byte*) field->null_ptr - 01070 share->default_values); 01071 key_part->null_bit= field->null_bit; 01072 key_part->store_length+=HA_KEY_NULL_LENGTH; 01073 keyinfo->flags|=HA_NULL_PART_KEY; 01074 keyinfo->extra_length+= HA_KEY_NULL_LENGTH; 01075 keyinfo->key_length+= HA_KEY_NULL_LENGTH; 01076 } 01077 if (field->type() == FIELD_TYPE_BLOB || 01078 field->real_type() == MYSQL_TYPE_VARCHAR) 01079 { 01080 if (field->type() == FIELD_TYPE_BLOB) 01081 key_part->key_part_flag|= HA_BLOB_PART; 01082 else 01083 key_part->key_part_flag|= HA_VAR_LENGTH_PART; 01084 keyinfo->extra_length+=HA_KEY_BLOB_LENGTH; 01085 key_part->store_length+=HA_KEY_BLOB_LENGTH; 01086 keyinfo->key_length+= HA_KEY_BLOB_LENGTH; 01087 /* 01088 Mark that there may be many matching values for one key 01089 combination ('a', 'a ', 'a '...) 01090 */ 01091 if (!(field->flags & BINARY_FLAG)) 01092 keyinfo->flags|= HA_END_SPACE_KEY; 01093 } 01094 if (field->type() == MYSQL_TYPE_BIT) 01095 key_part->key_part_flag|= HA_BIT_PART; 01096 01097 if (i == 0 && key != primary_key) 01098 field->flags |= (((keyinfo->flags & HA_NOSAME) && 01099 (keyinfo->key_parts == 1)) ? 01100 UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG); 01101 if (i == 0) 01102 field->key_start.set_bit(key); 01103 if (field->key_length() == key_part->length && 01104 !(field->flags & BLOB_FLAG)) 01105 { 01106 if (handler_file->index_flags(key, i, 0) & HA_KEYREAD_ONLY) 01107 { 01108 share->keys_for_keyread.set_bit(key); 01109 field->part_of_key.set_bit(key); 01110 field->part_of_key_not_clustered.set_bit(key); 01111 } 01112 if (handler_file->index_flags(key, i, 1) & HA_READ_ORDER) 01113 field->part_of_sortkey.set_bit(key); 01114 } 01115 if (!(key_part->key_part_flag & HA_REVERSE_SORT) && 01116 usable_parts == i) 01117 usable_parts++; // For FILESORT 01118 field->flags|= PART_KEY_FLAG; 01119 if (key == primary_key) 01120 { 01121 field->flags|= PRI_KEY_FLAG; 01122 /* 01123 If this field is part of the primary key and all keys contains 01124 the primary key, then we can use any key to find this column 01125 */ 01126 if (ha_option & HA_PRIMARY_KEY_IN_READ_INDEX) 01127 field->part_of_key= share->keys_in_use; 01128 } 01129 if (field->key_length() != key_part->length) 01130 { 01131 #ifndef TO_BE_DELETED_ON_PRODUCTION 01132 if (field->type() == FIELD_TYPE_NEWDECIMAL) 01133 { 01134 /* 01135 Fix a fatal error in decimal key handling that causes crashes 01136 on Innodb. We fix it by reducing the key length so that 01137 InnoDB never gets a too big key when searching. 01138 This allows the end user to do an ALTER TABLE to fix the 01139 error. 01140 */ 01141 keyinfo->key_length-= (key_part->length - field->key_length()); 01142 key_part->store_length-= (uint16)(key_part->length - 01143 field->key_length()); 01144 key_part->length= (uint16)field->key_length(); 01145 sql_print_error("Found wrong key definition in %s; " 01146 "Please do \"ALTER TABLE '%s' FORCE \" to fix it!", 01147 share->table_name.str, 01148 share->table_name.str); 01149 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, 01150 ER_CRASHED_ON_USAGE, 01151 "Found wrong key definition in %s; " 01152 "Please do \"ALTER TABLE '%s' FORCE\" to fix " 01153 "it!", 01154 share->table_name.str, 01155 share->table_name.str); 01156 share->crashed= 1; // Marker for CHECK TABLE 01157 goto to_be_deleted; 01158 } 01159 #endif 01160 key_part->key_part_flag|= HA_PART_KEY_SEG; 01161 } 01162 01163 to_be_deleted: 01164 01165 /* 01166 If the field can be NULL, don't optimize away the test 01167 key_part_column = expression from the WHERE clause 01168 as we need to test for NULL = NULL. 01169 */ 01170 if (field->real_maybe_null()) 01171 key_part->key_part_flag|= HA_PART_KEY_SEG; 01172 } 01173 keyinfo->usable_key_parts= usable_parts; // Filesort 01174 01175 set_if_bigger(share->max_key_length,keyinfo->key_length+ 01176 keyinfo->key_parts); 01177 share->total_key_length+= keyinfo->key_length; 01178 /* 01179 MERGE tables do not have unique indexes. But every key could be 01180 an unique index on the underlying MyISAM table. (Bug #10400) 01181 */ 01182 if ((keyinfo->flags & HA_NOSAME) || 01183 (ha_option & HA_ANY_INDEX_MAY_BE_UNIQUE)) 01184 set_if_bigger(share->max_unique_length,keyinfo->key_length); 01185 } 01186 if (primary_key < MAX_KEY && 01187 (share->keys_in_use.is_set(primary_key))) 01188 { 01189 share->primary_key= primary_key; 01190 /* 01191 If we are using an integer as the primary key then allow the user to 01192 refer to it as '_rowid' 01193 */ 01194 if (share->key_info[primary_key].key_parts == 1) 01195 { 01196 Field *field= share->key_info[primary_key].key_part[0].field; 01197 if (field && field->result_type() == INT_RESULT) 01198 { 01199 /* note that fieldnr here (and rowid_field_offset) starts from 1 */ 01200 share->rowid_field_offset= (share->key_info[primary_key].key_part[0]. 01201 fieldnr); 01202 } 01203 } 01204 } 01205 else 01206 share->primary_key = MAX_KEY; // we do not have a primary key 01207 } 01208 else 01209 share->primary_key= MAX_KEY; 01210 x_free((gptr) disk_buff); 01211 disk_buff=0; 01212 if (new_field_pack_flag <= 1) 01213 { 01214 /* Old file format with default as not null */ 01215 uint null_length= (share->null_fields+7)/8; 01216 bfill(share->default_values + (null_flags - (uchar*) record), 01217 null_length, 255); 01218 } 01219 01220 if (share->found_next_number_field) 01221 { 01222 /* 01223 We must have a table object for find_ref_key to calculate field offset 01224 */ 01225 TABLE tmp_table; 01226 tmp_table.record[0]= share->default_values; 01227 01228 reg_field= *share->found_next_number_field; 01229 reg_field->table= &tmp_table; 01230 if ((int) (share->next_number_index= (uint) 01231 find_ref_key(share->key_info, share->keys, reg_field, 01232 &share->next_number_key_offset)) < 0) 01233 { 01234 reg_field->unireg_check= Field::NONE; /* purecov: inspected */ 01235 share->found_next_number_field= 0; 01236 } 01237 else 01238 reg_field->flags |= AUTO_INCREMENT_FLAG; 01239 reg_field->table= 0; 01240 } 01241 01242 if (share->blob_fields) 01243 { 01244 Field **ptr; 01245 uint i, *save; 01246 01247 /* Store offsets to blob fields to find them fast */ 01248 if (!(share->blob_field= save= 01249 (uint*) alloc_root(&share->mem_root, 01250 (uint) (share->blob_fields* sizeof(uint))))) 01251 goto err; 01252 for (i=0, ptr= share->field ; *ptr ; ptr++, i++) 01253 { 01254 if ((*ptr)->flags & BLOB_FLAG) 01255 (*save++)= i; 01256 } 01257 } 01258 01259 /* 01260 the correct null_bytes can now be set, since bitfields have been taken 01261 into account 01262 */ 01263 share->null_bytes= (null_pos - (uchar*) null_flags + 01264 (null_bit_pos + 7) / 8); 01265 share->last_null_bit_pos= null_bit_pos; 01266 01267 share->db_low_byte_first= handler_file->low_byte_first(); 01268 share->column_bitmap_size= bitmap_buffer_size(share->fields); 01269 01270 if (!(bitmaps= (my_bitmap_map*) alloc_root(&share->mem_root, 01271 share->column_bitmap_size))) 01272 goto err; 01273 bitmap_init(&share->all_set, bitmaps, share->fields, FALSE); 01274 bitmap_set_all(&share->all_set); 01275 01276 delete handler_file; 01277 #ifndef DBUG_OFF 01278 if (use_hash) 01279 (void) hash_check(&share->name_hash); 01280 #endif 01281 DBUG_RETURN (0); 01282 01283 err: 01284 share->error= error; 01285 share->open_errno= my_errno; 01286 share->errarg= errarg; 01287 x_free((gptr) disk_buff); 01288 delete crypted; 01289 delete handler_file; 01290 hash_free(&share->name_hash); 01291 01292 open_table_error(share, error, share->open_errno, errarg); 01293 DBUG_RETURN(error); 01294 } /* open_binary_frm */ 01295 01296 01297 /* 01298 Open a table based on a TABLE_SHARE 01299 01300 SYNOPSIS 01301 open_table_from_share() 01302 thd Thread handler 01303 share Table definition 01304 alias Alias for table 01305 db_stat open flags (for example HA_OPEN_KEYFILE| 01306 HA_OPEN_RNDFILE..) can be 0 (example in 01307 ha_example_table) 01308 prgflag READ_ALL etc.. 01309 ha_open_flags HA_OPEN_ABORT_IF_LOCKED etc.. 01310 outparam result table 01311 01312 RETURN VALUES 01313 0 ok 01314 1 Error (see open_table_error) 01315 2 Error (see open_table_error) 01316 3 Wrong data in .frm file 01317 4 Error (see open_table_error) 01318 5 Error (see open_table_error: charset unavailable) 01319 7 Table definition has changed in engine 01320 */ 01321 01322 int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, 01323 uint db_stat, uint prgflag, uint ha_open_flags, 01324 TABLE *outparam, bool is_create_table) 01325 { 01326 int error; 01327 uint records, i, bitmap_size; 01328 bool error_reported= FALSE; 01329 byte *record, *bitmaps; 01330 Field **field_ptr; 01331 DBUG_ENTER("open_table_from_share"); 01332 DBUG_PRINT("enter",("name: '%s.%s' form: 0x%lx", share->db.str, 01333 share->table_name.str, outparam)); 01334 01335 error= 1; 01336 bzero((char*) outparam, sizeof(*outparam)); 01337 outparam->in_use= thd; 01338 outparam->s= share; 01339 outparam->db_stat= db_stat; 01340 outparam->write_row_record= NULL; 01341 01342 init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); 01343 01344 if (!(outparam->alias= my_strdup(alias, MYF(MY_WME)))) 01345 goto err; 01346 outparam->quick_keys.init(); 01347 outparam->used_keys.init(); 01348 outparam->keys_in_use_for_query.init(); 01349 01350 /* Allocate handler */ 01351 if (!(outparam->file= get_new_handler(share, &outparam->mem_root, 01352 share->db_type))) 01353 goto err; 01354 01355 error= 4; 01356 outparam->reginfo.lock_type= TL_UNLOCK; 01357 outparam->current_lock= F_UNLCK; 01358 records=0; 01359 if ((db_stat & HA_OPEN_KEYFILE) || (prgflag & DELAYED_OPEN)) 01360 records=1; 01361 if (prgflag & (READ_ALL+EXTRA_RECORD)) 01362 records++; 01363 01364 if (!(record= (byte*) alloc_root(&outparam->mem_root, 01365 share->rec_buff_length * records))) 01366 goto err; /* purecov: inspected */ 01367 01368 if (records == 0) 01369 { 01370 /* We are probably in hard repair, and the buffers should not be used */ 01371 outparam->record[0]= outparam->record[1]= share->default_values; 01372 } 01373 else 01374 { 01375 outparam->record[0]= record; 01376 if (records > 1) 01377 outparam->record[1]= record+ share->rec_buff_length; 01378 else 01379 outparam->record[1]= outparam->record[0]; // Safety 01380 } 01381 01382 #ifdef HAVE_purify 01383 /* 01384 We need this because when we read var-length rows, we are not updating 01385 bytes after end of varchar 01386 */ 01387 if (records > 1) 01388 { 01389 memcpy(outparam->record[0], share->default_values, share->rec_buff_length); 01390 if (records > 2) 01391 memcpy(outparam->record[1], share->default_values, 01392 share->rec_buff_length); 01393 } 01394 #endif 01395 01396 if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, 01397 (uint) ((share->fields+1)* 01398 sizeof(Field*))))) 01399 goto err; /* purecov: inspected */ 01400 01401 outparam->field= field_ptr; 01402 01403 record= (byte*) outparam->record[0]-1; /* Fieldstart = 1 */ 01404 if (share->null_field_first) 01405 outparam->null_flags= (uchar*) record+1; 01406 else 01407 outparam->null_flags= (uchar*) (record+ 1+ share->reclength - 01408 share->null_bytes); 01409 01410 /* Setup copy of fields from share, but use the right alias and record */ 01411 for (i=0 ; i < share->fields; i++, field_ptr++) 01412 { 01413 if (!((*field_ptr)= share->field[i]->clone(&outparam->mem_root, outparam))) 01414 goto err; 01415 } 01416 (*field_ptr)= 0; // End marker 01417 01418 if (share->found_next_number_field) 01419 outparam->found_next_number_field= 01420 outparam->field[(uint) (share->found_next_number_field - share->field)]; 01421 if (share->timestamp_field) 01422 outparam->timestamp_field= (Field_timestamp*) outparam->field[share->timestamp_field_offset]; 01423 01424 01425 /* Fix key->name and key_part->field */ 01426 if (share->key_parts) 01427 { 01428 KEY *key_info, *key_info_end; 01429 KEY_PART_INFO *key_part; 01430 uint n_length; 01431 n_length= share->keys*sizeof(KEY) + share->key_parts*sizeof(KEY_PART_INFO); 01432 if (!(key_info= (KEY*) alloc_root(&outparam->mem_root, n_length))) 01433 goto err; 01434 outparam->key_info= key_info; 01435 key_part= (my_reinterpret_cast(KEY_PART_INFO*) (key_info+share->keys)); 01436 01437 memcpy(key_info, share->key_info, sizeof(*key_info)*share->keys); 01438 memcpy(key_part, share->key_info[0].key_part, (sizeof(*key_part) * 01439 share->key_parts)); 01440 01441 for (key_info_end= key_info + share->keys ; 01442 key_info < key_info_end ; 01443 key_info++) 01444 { 01445 KEY_PART_INFO *key_part_end; 01446 01447 key_info->table= outparam; 01448 key_info->key_part= key_part; 01449 01450 for (key_part_end= key_part+ key_info->key_parts ; 01451 key_part < key_part_end ; 01452 key_part++) 01453 { 01454 Field *field= key_part->field= outparam->field[key_part->fieldnr-1]; 01455 01456 if (field->key_length() != key_part->length && 01457 !(field->flags & BLOB_FLAG)) 01458 { 01459 /* 01460 We are using only a prefix of the column as a key: 01461 Create a new field for the key part that matches the index 01462 */ 01463 field= key_part->field=field->new_field(&outparam->mem_root, 01464 outparam, 0); 01465 field->field_length= key_part->length; 01466 } 01467 } 01468 } 01469 } 01470 01471 #ifdef WITH_PARTITION_STORAGE_ENGINE 01472 if (share->partition_info_len) 01473 { 01474 MEM_ROOT **root_ptr, *old_root; 01475 bool tmp; 01476 root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); 01477 old_root= *root_ptr; 01478 *root_ptr= &outparam->mem_root; 01479 01480 tmp= mysql_unpack_partition(thd, share->partition_info, 01481 share->partition_info_len, 01482 (uchar*)share->part_state, 01483 share->part_state_len, 01484 outparam, is_create_table, 01485 share->default_part_db_type); 01486 outparam->part_info->is_auto_partitioned= share->auto_partitioned; 01487 DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); 01488 if (!tmp) 01489 tmp= fix_partition_func(thd, outparam, is_create_table); 01490 *root_ptr= old_root; 01491 if (tmp) 01492 { 01493 if (is_create_table) 01494 { 01495 /* 01496 During CREATE/ALTER TABLE it is ok to receive errors here. 01497 It is not ok if it happens during the opening of an frm 01498 file as part of a normal query. 01499 */ 01500 error_reported= TRUE; 01501 } 01502 goto err; 01503 } 01504 } 01505 #endif 01506 01507 /* Allocate bitmaps */ 01508 01509 bitmap_size= share->column_bitmap_size; 01510 if (!(bitmaps= (byte*) alloc_root(&outparam->mem_root, bitmap_size*3))) 01511 goto err; 01512 bitmap_init(&outparam->def_read_set, 01513 (my_bitmap_map*) bitmaps, share->fields, FALSE); 01514 bitmap_init(&outparam->def_write_set, 01515 (my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE); 01516 bitmap_init(&outparam->tmp_set, 01517 (my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE); 01518 outparam->default_column_bitmaps(); 01519 01520 /* The table struct is now initialized; Open the table */ 01521 error= 2; 01522 if (db_stat) 01523 { 01524 int ha_err; 01525 if ((ha_err= (outparam->file-> 01526 ha_open(outparam, share->normalized_path.str, 01527 (db_stat & HA_READ_ONLY ? O_RDONLY : O_RDWR), 01528 (db_stat & HA_OPEN_TEMPORARY ? HA_OPEN_TMP_TABLE : 01529 ((db_stat & HA_WAIT_IF_LOCKED) || 01530 (specialflag & SPECIAL_WAIT_IF_LOCKED)) ? 01531 HA_OPEN_WAIT_IF_LOCKED : 01532 (db_stat & (HA_ABORT_IF_LOCKED | HA_GET_INFO)) ? 01533 HA_OPEN_ABORT_IF_LOCKED : 01534 HA_OPEN_IGNORE_IF_LOCKED) | ha_open_flags)))) 01535 { 01536 /* Set a flag if the table is crashed and it can be auto. repaired */ 01537 share->crashed= ((ha_err == HA_ERR_CRASHED_ON_USAGE) && 01538 outparam->file->auto_repair() && 01539 !(ha_open_flags & HA_OPEN_FOR_REPAIR)); 01540 01541 if (ha_err == HA_ERR_NO_SUCH_TABLE) 01542 { 01543 /* 01544 The table did not exists in storage engine, use same error message 01545 as if the .frm file didn't exist 01546 */ 01547 error= 1; 01548 my_errno= ENOENT; 01549 } 01550 else 01551 { 01552 outparam->file->print_error(ha_err, MYF(0)); 01553 error_reported= TRUE; 01554 if (ha_err == HA_ERR_TABLE_DEF_CHANGED) 01555 error= 7; 01556 } 01557 goto err; /* purecov: inspected */ 01558 } 01559 } 01560 01561 #if defined(HAVE_purify) && !defined(DBUG_OFF) 01562 bzero((char*) bitmaps, bitmap_size*3); 01563 #endif 01564 01565 thd->status_var.opened_tables++; 01566 01567 DBUG_RETURN (0); 01568 01569 err: 01570 if (! error_reported) 01571 open_table_error(share, error, my_errno, 0); 01572 delete outparam->file; 01573 #ifdef WITH_PARTITION_STORAGE_ENGINE 01574 if (outparam->part_info) 01575 free_items(outparam->part_info->item_free_list); 01576 #endif 01577 outparam->file= 0; // For easier error checking 01578 outparam->db_stat=0; 01579 free_root(&outparam->mem_root, MYF(0)); // Safe to call on bzero'd root 01580 my_free((char*) outparam->alias, MYF(MY_ALLOW_ZERO_PTR)); 01581 DBUG_RETURN (error); 01582 } 01583 01584 01585 /* 01586 Free information allocated by openfrm 01587 01588 SYNOPSIS 01589 closefrm() 01590 table TABLE object to free 01591 free_share Is 1 if we also want to free table_share 01592 */ 01593 01594 int closefrm(register TABLE *table, bool free_share) 01595 { 01596 int error=0; 01597 uint idx; 01598 KEY *key_info; 01599 DBUG_ENTER("closefrm"); 01600 DBUG_PRINT("enter", ("table: 0x%lx", (long) table)); 01601 01602 if (table->db_stat) 01603 error=table->file->close(); 01604 key_info= table->key_info; 01605 for (idx= table->s->keys; idx; idx--, key_info++) 01606 { 01607 if (key_info->flags & HA_USES_PARSER) 01608 { 01609 plugin_unlock(key_info->parser); 01610 key_info->flags= 0; 01611 } 01612 } 01613 my_free((char*) table->alias, MYF(MY_ALLOW_ZERO_PTR)); 01614 table->alias= 0; 01615 if (table->field) 01616 { 01617 for (Field **ptr=table->field ; *ptr ; ptr++) 01618 delete *ptr; 01619 table->field= 0; 01620 } 01621 delete table->file; 01622 table->file= 0; /* For easier errorchecking */ 01623 #ifdef WITH_PARTITION_STORAGE_ENGINE 01624 if (table->part_info) 01625 { 01626 free_items(table->part_info->item_free_list); 01627 table->part_info->item_free_list= 0; 01628 table->part_info= 0; 01629 } 01630 #endif 01631 if (free_share) 01632 { 01633 if (table->s->tmp_table == NO_TMP_TABLE) 01634 release_table_share(table->s, RELEASE_NORMAL); 01635 else 01636 free_table_share(table->s); 01637 } 01638 free_root(&table->mem_root, MYF(0)); 01639 DBUG_RETURN(error); 01640 } 01641 01642 01643 /* Deallocate temporary blob storage */ 01644 01645 void free_blobs(register TABLE *table) 01646 { 01647 uint *ptr, *end; 01648 for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ; 01649 ptr != end ; 01650 ptr++) 01651 ((Field_blob*) table->field[*ptr])->free(); 01652 } 01653 01654 01655 /* Find where a form starts */ 01656 /* if formname is NullS then only formnames is read */ 01657 01658 ulong get_form_pos(File file, uchar *head, TYPELIB *save_names) 01659 { 01660 uint a_length,names,length; 01661 uchar *pos,*buf; 01662 ulong ret_value=0; 01663 DBUG_ENTER("get_form_pos"); 01664 01665 names=uint2korr(head+8); 01666 a_length=(names+2)*sizeof(my_string); /* Room for two extra */ 01667 01668 if (!save_names) 01669 a_length=0; 01670 else 01671 save_names->type_names=0; /* Clear if error */ 01672 01673 if (names) 01674 { 01675 length=uint2korr(head+4); 01676 VOID(my_seek(file,64L,MY_SEEK_SET,MYF(0))); 01677 if (!(buf= (uchar*) my_malloc((uint) length+a_length+names*4, 01678 MYF(MY_WME))) || 01679 my_read(file,(byte*) buf+a_length,(uint) (length+names*4), 01680 MYF(MY_NABP))) 01681 { /* purecov: inspected */ 01682 x_free((gptr) buf); /* purecov: inspected */ 01683 DBUG_RETURN(0L); /* purecov: inspected */ 01684 } 01685 pos= buf+a_length+length; 01686 ret_value=uint4korr(pos); 01687 } 01688 if (! save_names) 01689 { 01690 if (names) 01691 my_free((gptr) buf,MYF(0)); 01692 } 01693 else if (!names) 01694 bzero((char*) save_names,sizeof(save_names)); 01695 else 01696 { 01697 char *str; 01698 str=(char *) (buf+a_length); 01699 fix_type_pointers((const char ***) &buf,save_names,1,&str); 01700 } 01701 DBUG_RETURN(ret_value); 01702 } 01703 01704 01705 /* Read string from a file with malloc */ 01706 01707 int read_string(File file, gptr *to, uint length) 01708 { 01709 DBUG_ENTER("read_string"); 01710 01711 x_free((gptr) *to); 01712 if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) || 01713 my_read(file,(byte*) *to,length,MYF(MY_NABP))) 01714 { 01715 x_free((gptr) *to); /* purecov: inspected */ 01716 *to= 0; /* purecov: inspected */ 01717 DBUG_RETURN(1); /* purecov: inspected */ 01718 } 01719 *((char*) *to+length)= '\0'; 01720 DBUG_RETURN (0); 01721 } /* read_string */ 01722 01723 01724 /* Add a new form to a form file */ 01725 01726 ulong make_new_entry(File file, uchar *fileinfo, TYPELIB *formnames, 01727 const char *newname) 01728 { 01729 uint i,bufflength,maxlength,n_length,length,names; 01730 ulong endpos,newpos; 01731 char buff[IO_SIZE]; 01732 uchar *pos; 01733 DBUG_ENTER("make_new_entry"); 01734 01735 length=(uint) strlen(newname)+1; 01736 n_length=uint2korr(fileinfo+4); 01737 maxlength=uint2korr(fileinfo+6); 01738 names=uint2korr(fileinfo+8); 01739 newpos=uint4korr(fileinfo+10); 01740 01741 if (64+length+n_length+(names+1)*4 > maxlength) 01742 { /* Expand file */ 01743 newpos+=IO_SIZE; 01744 int4store(fileinfo+10,newpos); 01745 endpos=(ulong) my_seek(file,0L,MY_SEEK_END,MYF(0));/* Copy from file-end */ 01746 bufflength= (uint) (endpos & (IO_SIZE-1)); /* IO_SIZE is a power of 2 */ 01747 01748 while (endpos > maxlength) 01749 { 01750 VOID(my_seek(file,(ulong) (endpos-bufflength),MY_SEEK_SET,MYF(0))); 01751 if (my_read(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))) 01752 DBUG_RETURN(0L); 01753 VOID(my_seek(file,(ulong) (endpos-bufflength+IO_SIZE),MY_SEEK_SET, 01754 MYF(0))); 01755 if ((my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME)))) 01756 DBUG_RETURN(0); 01757 endpos-=bufflength; bufflength=IO_SIZE; 01758 } 01759 bzero(buff,IO_SIZE); /* Null new block */ 01760 VOID(my_seek(file,(ulong) maxlength,MY_SEEK_SET,MYF(0))); 01761 if (my_write(file,(byte*) buff,bufflength,MYF(MY_NABP+MY_WME))) 01762 DBUG_RETURN(0L); 01763 maxlength+=IO_SIZE; /* Fix old ref */ 01764 int2store(fileinfo+6,maxlength); 01765 for (i=names, pos= (uchar*) *formnames->type_names+n_length-1; i-- ; 01766 pos+=4) 01767 { 01768 endpos=uint4korr(pos)+IO_SIZE; 01769 int4store(pos,endpos); 01770 } 01771 } 01772 01773 if (n_length == 1 ) 01774 { /* First name */ 01775 length++; 01776 VOID(strxmov(buff,"/",newname,"/",NullS)); 01777 } 01778 else 01779 VOID(strxmov(buff,newname,"/",NullS)); /* purecov: inspected */ 01780 VOID(my_seek(file,63L+(ulong) n_length,MY_SEEK_SET,MYF(0))); 01781 if (my_write(file,(byte*) buff,(uint) length+1,MYF(MY_NABP+MY_WME)) || 01782 (names && my_write(file,(byte*) (*formnames->type_names+n_length-1), 01783 names*4, MYF(MY_NABP+MY_WME))) || 01784 my_write(file,(byte*) fileinfo+10,(uint) 4,MYF(MY_NABP+MY_WME))) 01785 DBUG_RETURN(0L); /* purecov: inspected */ 01786 01787 int2store(fileinfo+8,names+1); 01788 int2store(fileinfo+4,n_length+length); 01789 VOID(my_chsize(file, newpos, 0, MYF(MY_WME)));/* Append file with '\0' */ 01790 DBUG_RETURN(newpos); 01791 } /* make_new_entry */ 01792 01793 01794 /* error message when opening a form file */ 01795 01796 void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg) 01797 { 01798 int err_no; 01799 char buff[FN_REFLEN]; 01800 myf errortype= ME_ERROR+ME_WAITTANG; 01801 DBUG_ENTER("open_table_error"); 01802 01803 switch (error) { 01804 case 7: 01805 case 1: 01806 if (db_errno == ENOENT) 01807 my_error(ER_NO_SUCH_TABLE, MYF(0), share->db.str, share->table_name.str); 01808 else 01809 { 01810 strxmov(buff, share->normalized_path.str, reg_ext, NullS); 01811 my_error((db_errno == EMFILE) ? ER_CANT_OPEN_FILE : ER_FILE_NOT_FOUND, 01812 errortype, buff, db_errno); 01813 } 01814 break; 01815 case 2: 01816 { 01817 handler *file= 0; 01818 const char *datext= ""; 01819 01820 if (share->db_type != NULL) 01821 { 01822 if ((file= get_new_handler(share, current_thd->mem_root, 01823 share->db_type))) 01824 { 01825 if (!(datext= *file->bas_ext())) 01826 datext= ""; 01827 } 01828 } 01829 err_no= (db_errno == ENOENT) ? ER_FILE_NOT_FOUND : (db_errno == EAGAIN) ? 01830 ER_FILE_USED : ER_CANT_OPEN_FILE; 01831 strxmov(buff, share->normalized_path.str, datext, NullS); 01832 my_error(err_no,errortype, buff, db_errno); 01833 delete file; 01834 break; 01835 } 01836 case 5: 01837 { 01838 const char *csname= get_charset_name((uint) errarg); 01839 char tmp[10]; 01840 if (!csname || csname[0] =='?') 01841 { 01842 my_snprintf(tmp, sizeof(tmp), "#%d", errarg); 01843 csname= tmp; 01844 } 01845 my_printf_error(ER_UNKNOWN_COLLATION, 01846 "Unknown collation '%s' in table '%-.64s' definition", 01847 MYF(0), csname, share->table_name.str); 01848 break; 01849 } 01850 case 6: 01851 strxmov(buff, share->normalized_path.str, reg_ext, NullS); 01852 my_printf_error(ER_NOT_FORM_FILE, 01853 "Table '%-.64s' was created with a different version " 01854 "of MySQL and cannot be read", 01855 MYF(0), buff); 01856 break; 01857 default: /* Better wrong error than none */ 01858 case 4: 01859 strxmov(buff, share->normalized_path.str, reg_ext, NullS); 01860 my_error(ER_NOT_FORM_FILE, errortype, buff, 0); 01861 break; 01862 } 01863 DBUG_VOID_RETURN; 01864 } /* open_table_error */ 01865 01866 01867 /* 01868 ** fix a str_type to a array type 01869 ** typeparts separated with some char. differents types are separated 01870 ** with a '\0' 01871 */ 01872 01873 static void 01874 fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, 01875 char **names) 01876 { 01877 char *type_name, *ptr; 01878 char chr; 01879 01880 ptr= *names; 01881 while (types--) 01882 { 01883 point_to_type->name=0; 01884 point_to_type->type_names= *array; 01885 01886 if ((chr= *ptr)) /* Test if empty type */ 01887 { 01888 while ((type_name=strchr(ptr+1,chr)) != NullS) 01889 { 01890 *((*array)++) = ptr+1; 01891 *type_name= '\0'; /* End string */ 01892 ptr=type_name; 01893 } 01894 ptr+=2; /* Skip end mark and last 0 */ 01895 } 01896 else 01897 ptr++; 01898 point_to_type->count= (uint) (*array - point_to_type->type_names); 01899 point_to_type++; 01900 *((*array)++)= NullS; /* End of type */ 01901 } 01902 *names=ptr; /* Update end */ 01903 return; 01904 } /* fix_type_pointers */ 01905 01906 01907 TYPELIB *typelib(MEM_ROOT *mem_root, List<String> &strings) 01908 { 01909 TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB)); 01910 if (!result) 01911 return 0; 01912 result->count=strings.elements; 01913 result->name=""; 01914 uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1); 01915 if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes))) 01916 return 0; 01917 result->type_lengths= (uint*) (result->type_names + result->count + 1); 01918 List_iterator<String> it(strings); 01919 String *tmp; 01920 for (uint i=0; (tmp=it++) ; i++) 01921 { 01922 result->type_names[i]= tmp->ptr(); 01923 result->type_lengths[i]= tmp->length(); 01924 } 01925 result->type_names[result->count]= 0; // End marker 01926 result->type_lengths[result->count]= 0; 01927 return result; 01928 } 01929 01930 01931 /* 01932 Search after a field with given start & length 01933 If an exact field isn't found, return longest field with starts 01934 at right position. 01935 01936 NOTES 01937 This is needed because in some .frm fields 'fieldnr' was saved wrong 01938 01939 RETURN 01940 0 error 01941 # field number +1 01942 */ 01943 01944 static uint find_field(Field **fields, uint start, uint length) 01945 { 01946 Field **field; 01947 uint i, pos; 01948 01949 pos= 0; 01950 for (field= fields, i=1 ; *field ; i++,field++) 01951 { 01952 if ((*field)->offset() == start) 01953 { 01954 if ((*field)->key_length() == length) 01955 return (i); 01956 if (!pos || fields[pos-1]->pack_length() < 01957 (*field)->pack_length()) 01958 pos= i; 01959 } 01960 } 01961 return (pos); 01962 } 01963 01964 01965 /* Check that the integer is in the internal */ 01966 01967 int set_zone(register int nr, int min_zone, int max_zone) 01968 { 01969 if (nr<=min_zone) 01970 return (min_zone); 01971 if (nr>=max_zone) 01972 return (max_zone); 01973 return (nr); 01974 } /* set_zone */ 01975 01976 /* Adjust number to next larger disk buffer */ 01977 01978 ulong next_io_size(register ulong pos) 01979 { 01980 reg2 ulong offset; 01981 if ((offset= pos & (IO_SIZE-1))) 01982 return pos-offset+IO_SIZE; 01983 return pos; 01984 } /* next_io_size */ 01985 01986 01987 /* 01988 Store an SQL quoted string. 01989 01990 SYNOPSIS 01991 append_unescaped() 01992 res result String 01993 pos string to be quoted 01994 length it's length 01995 01996 NOTE 01997 This function works correctly with utf8 or single-byte charset strings. 01998 May fail with some multibyte charsets though. 01999 */ 02000 02001 void append_unescaped(String *res, const char *pos, uint length) 02002 { 02003 const char *end= pos+length; 02004 res->append('\''); 02005 02006 for (; pos != end ; pos++) 02007 { 02008 #if defined(USE_MB) && MYSQL_VERSION_ID < 40100 02009 uint mblen; 02010 if (use_mb(default_charset_info) && 02011 (mblen= my_ismbchar(default_charset_info, pos, end))) 02012 { 02013 res->append(pos, mblen); 02014 pos+= mblen; 02015 continue; 02016 } 02017 #endif 02018 02019 switch (*pos) { 02020 case 0: /* Must be escaped for 'mysql' */ 02021 res->append('\\'); 02022 res->append('0'); 02023 break; 02024 case '\n': /* Must be escaped for logs */ 02025 res->append('\\'); 02026 res->append('n'); 02027 break; 02028 case '\r': 02029 res->append('\\'); /* This gives better readability */ 02030 res->append('r'); 02031 break; 02032 case '\\': 02033 res->append('\\'); /* Because of the sql syntax */ 02034 res->append('\\'); 02035 break; 02036 case '\'': 02037 res->append('\''); /* Because of the sql syntax */ 02038 res->append('\''); 02039 break; 02040 default: 02041 res->append(*pos); 02042 break; 02043 } 02044 } 02045 res->append('\''); 02046 } 02047 02048 02049 /* Create a .frm file */ 02050 02051 File create_frm(THD *thd, const char *name, const char *db, 02052 const char *table, uint reclength, uchar *fileinfo, 02053 HA_CREATE_INFO *create_info, uint keys) 02054 { 02055 register File file; 02056 uint key_length; 02057 ulong length; 02058 char fill[IO_SIZE]; 02059 int create_flags= O_RDWR | O_TRUNC; 02060 02061 if (create_info->options & HA_LEX_CREATE_TMP_TABLE) 02062 create_flags|= O_EXCL | O_NOFOLLOW; 02063 02064 /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */ 02065 if (create_info->max_rows > UINT_MAX32) 02066 create_info->max_rows= UINT_MAX32; 02067 if (create_info->min_rows > UINT_MAX32) 02068 create_info->min_rows= UINT_MAX32; 02069 02070 if ((file= my_create(name, CREATE_MODE, create_flags, MYF(0))) >= 0) 02071 { 02072 uint key_length, tmp_key_length; 02073 uint tmp; 02074 bzero((char*) fileinfo,64); 02075 /* header */ 02076 fileinfo[0]=(uchar) 254; 02077 fileinfo[1]= 1; 02078 fileinfo[2]= FRM_VER+3+ test(create_info->varchar); 02079 02080 fileinfo[3]= (uchar) ha_legacy_type( 02081 ha_checktype(thd,ha_legacy_type(create_info->db_type),0,0)); 02082 fileinfo[4]=1; 02083 int2store(fileinfo+6,IO_SIZE); /* Next block starts here */ 02084 key_length=keys*(7+NAME_LEN+MAX_REF_PARTS*9)+16; 02085 length= next_io_size((ulong) (IO_SIZE+key_length+reclength+ 02086 create_info->extra_size)); 02087 int4store(fileinfo+10,length); 02088 tmp_key_length= (key_length < 0xffff) ? key_length : 0xffff; 02089 int2store(fileinfo+14,tmp_key_length); 02090 int2store(fileinfo+16,reclength); 02091 int4store(fileinfo+18,create_info->max_rows); 02092 int4store(fileinfo+22,create_info->min_rows); 02093 fileinfo[27]=2; // Use long pack-fields 02094 create_info->table_options|=HA_OPTION_LONG_BLOB_PTR; // Use portable blob pointers 02095 int2store(fileinfo+30,create_info->table_options); 02096 fileinfo[32]=0; // No filename anymore 02097 fileinfo[33]=5; // Mark for 5.0 frm file 02098 int4store(fileinfo+34,create_info->avg_row_length); 02099 fileinfo[38]= (create_info->default_table_charset ? 02100 create_info->default_table_charset->number : 0); 02101 fileinfo[40]= (uchar) create_info->row_type; 02102 /* Next few bytes were for RAID support */ 02103 fileinfo[41]= 0; 02104 fileinfo[42]= 0; 02105 fileinfo[43]= 0; 02106 fileinfo[44]= 0; 02107 fileinfo[45]= 0; 02108 fileinfo[46]= 0; 02109 int4store(fileinfo+47, key_length); 02110 tmp= MYSQL_VERSION_ID; // Store to avoid warning from int4store 02111 int4store(fileinfo+51, tmp); 02112 int4store(fileinfo+55, create_info->extra_size); 02113 /* 02114 59-60 is reserved for extra_rec_buf_length, 02115 61 for default_part_db_type 02116 */ 02117 int2store(fileinfo+62, create_info->key_block_size); 02118 bzero(fill,IO_SIZE); 02119 for (; length > IO_SIZE ; length-= IO_SIZE) 02120 { 02121 if (my_write(file,(byte*) fill,IO_SIZE,MYF(MY_WME | MY_NABP))) 02122 { 02123 VOID(my_close(file,MYF(0))); 02124 VOID(my_delete(name,MYF(0))); 02125 return(-1); 02126 } 02127 } 02128 } 02129 else 02130 { 02131 if (my_errno == ENOENT) 02132 my_error(ER_BAD_DB_ERROR,MYF(0),db); 02133 else 02134 my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno); 02135 } 02136 return (file); 02137 } /* create_frm */ 02138 02139 02140 void update_create_info_from_table(HA_CREATE_INFO *create_info, TABLE *table) 02141 { 02142 TABLE_SHARE *share= table->s; 02143 DBUG_ENTER("update_create_info_from_table"); 02144 02145 create_info->max_rows= share->max_rows; 02146 create_info->min_rows= share->min_rows; 02147 create_info->table_options= share->db_create_options; 02148 create_info->avg_row_length= share->avg_row_length; 02149 create_info->row_type= share->row_type; 02150 create_info->default_table_charset= share->table_charset; 02151 create_info->table_charset= 0; 02152 02153 DBUG_VOID_RETURN; 02154 } 02155 02156 int 02157 rename_file_ext(const char * from,const char * to,const char * ext) 02158 { 02159 char from_b[FN_REFLEN],to_b[FN_REFLEN]; 02160 VOID(strxmov(from_b,from,ext,NullS)); 02161 VOID(strxmov(to_b,to,ext,NullS)); 02162 return (my_rename(from_b,to_b,MYF(MY_WME))); 02163 } 02164 02165 02166 /* 02167 Allocate string field in MEM_ROOT and return it as String 02168 02169 SYNOPSIS 02170 get_field() 02171 mem MEM_ROOT for allocating 02172 field Field for retrieving of string 02173 res result String 02174 02175 RETURN VALUES 02176 1 string is empty 02177 0 all ok 02178 */ 02179 02180 bool get_field(MEM_ROOT *mem, Field *field, String *res) 02181 { 02182 char buff[MAX_FIELD_WIDTH], *to; 02183 String str(buff,sizeof(buff),&my_charset_bin); 02184 uint length; 02185 02186 field->val_str(&str); 02187 if (!(length= str.length())) 02188 { 02189 res->length(0); 02190 return 1; 02191 } 02192 if (!(to= strmake_root(mem, str.ptr(), length))) 02193 length= 0; // Safety fix 02194 res->set(to, length, ((Field_str*)field)->charset()); 02195 return 0; 02196 } 02197 02198 02199 /* 02200 Allocate string field in MEM_ROOT and return it as NULL-terminated string 02201 02202 SYNOPSIS 02203 get_field() 02204 mem MEM_ROOT for allocating 02205 field Field for retrieving of string 02206 02207 RETURN VALUES 02208 NullS string is empty 02209 # pointer to NULL-terminated string value of field 02210 */ 02211 02212 char *get_field(MEM_ROOT *mem, Field *field) 02213 { 02214 char buff[MAX_FIELD_WIDTH], *to; 02215 String str(buff,sizeof(buff),&my_charset_bin); 02216 uint length; 02217 02218 field->val_str(&str); 02219 length= str.length(); 02220 if (!length || !(to= (char*) alloc_root(mem,length+1))) 02221 return NullS; 02222 memcpy(to,str.ptr(),(uint) length); 02223 to[length]=0; 02224 return to; 02225 } 02226 02227 02228 /* 02229 Check if database name is valid 02230 02231 SYNPOSIS 02232 check_db_name() 02233 name Name of database 02234 02235 NOTES 02236 If lower_case_table_names is set then database is converted to lower case 02237 02238 RETURN 02239 0 ok 02240 1 error 02241 */ 02242 02243 bool check_db_name(char *name) 02244 { 02245 char *start=name; 02246 /* Used to catch empty names and names with end space */ 02247 bool last_char_is_space= TRUE; 02248 02249 if (lower_case_table_names && name != any_db) 02250 my_casedn_str(files_charset_info, name); 02251 02252 while (*name) 02253 { 02254 #if defined(USE_MB) && defined(USE_MB_IDENT) 02255 last_char_is_space= my_isspace(system_charset_info, *name); 02256 if (use_mb(system_charset_info)) 02257 { 02258 int len=my_ismbchar(system_charset_info, name, 02259 name+system_charset_info->mbmaxlen); 02260 if (len) 02261 { 02262 name += len; 02263 continue; 02264 } 02265 } 02266 #else 02267 last_char_is_space= *name==' '; 02268 #endif 02269 name++; 02270 } 02271 return last_char_is_space || (uint) (name - start) > NAME_LEN; 02272 } 02273 02274 02275 /* 02276 Allow anything as a table name, as long as it doesn't contain an 02277 ' ' at the end 02278 returns 1 on error 02279 */ 02280 02281 02282 bool check_table_name(const char *name, uint length) 02283 { 02284 const char *end= name+length; 02285 if (!length || length > NAME_LEN) 02286 return 1; 02287 #if defined(USE_MB) && defined(USE_MB_IDENT) 02288 bool last_char_is_space= FALSE; 02289 #else 02290 if (name[length-1]==' ') 02291 return 1; 02292 #endif 02293 02294 while (name != end) 02295 { 02296 #if defined(USE_MB) && defined(USE_MB_IDENT) 02297 last_char_is_space= my_isspace(system_charset_info, *name); 02298 if (use_mb(system_charset_info)) 02299 { 02300 int len=my_ismbchar(system_charset_info, name, end); 02301 if (len) 02302 { 02303 name += len; 02304 continue; 02305 } 02306 } 02307 #endif 02308 name++; 02309 } 02310 #if defined(USE_MB) && defined(USE_MB_IDENT) 02311 return last_char_is_space; 02312 #else 02313 return 0; 02314 #endif 02315 } 02316 02317 02318 bool check_column_name(const char *name) 02319 { 02320 const char *start= name; 02321 bool last_char_is_space= TRUE; 02322 02323 while (*name) 02324 { 02325 #if defined(USE_MB) && defined(USE_MB_IDENT) 02326 last_char_is_space= my_isspace(system_charset_info, *name); 02327 if (use_mb(system_charset_info)) 02328 { 02329 int len=my_ismbchar(system_charset_info, name, 02330 name+system_charset_info->mbmaxlen); 02331 if (len) 02332 { 02333 name += len; 02334 continue; 02335 } 02336 } 02337 #else 02338 last_char_is_space= *name==' '; 02339 #endif 02340 if (*name == NAMES_SEP_CHAR) 02341 return 1; 02342 name++; 02343 } 02344 /* Error if empty or too long column name */ 02345 return last_char_is_space || (uint) (name - start) > NAME_LEN; 02346 } 02347 02348 02349 /* 02350 Checks whether a table is intact. Should be done *just* after the table has 02351 been opened. 02352 02353 Synopsis 02354 table_check_intact() 02355 table - the table to check 02356 table_f_count - expected number of columns in the table 02357 table_def - expected structure of the table (column name and type) 02358 last_create_time- the table->file->create_time of the table in memory 02359 we have checked last time 02360 error_num - ER_XXXX from the error messages file. When 0 no error 02361 is sent to the client in case types does not match. 02362 If different col number either 02363 ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or 02364 ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used 02365 02366 RETURNS 02367 0 - OK 02368 1 - There was an error 02369 */ 02370 02371 my_bool 02372 table_check_intact(TABLE *table, uint table_f_count, 02373 TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time, 02374 int error_num) 02375 { 02376 uint i; 02377 my_bool error= FALSE; 02378 my_bool fields_diff_count; 02379 DBUG_ENTER("table_check_intact"); 02380 DBUG_PRINT("info",("table=%s expected_count=%d",table->alias, table_f_count)); 02381 DBUG_PRINT("info",("last_create_time=%d", *last_create_time)); 02382 02383 if ((fields_diff_count= (table->s->fields != table_f_count)) || 02384 (*last_create_time != table->file->stats.create_time)) 02385 { 02386 DBUG_PRINT("info", ("I am suspecting, checking table")); 02387 if (fields_diff_count) 02388 { 02389 // previous MySQL version 02390 error= TRUE; 02391 if (MYSQL_VERSION_ID > table->s->mysql_version) 02392 { 02393 my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias, 02394 table_f_count, table->s->fields, table->s->mysql_version, 02395 MYSQL_VERSION_ID); 02396 sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE), 02397 table->alias, table_f_count, table->s->fields, 02398 table->s->mysql_version, MYSQL_VERSION_ID); 02399 DBUG_RETURN(error); 02400 02401 } 02402 else if (MYSQL_VERSION_ID == table->s->mysql_version) 02403 { 02404 my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias, 02405 table_f_count, table->s->fields); 02406 sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias, 02407 table_f_count, table->s->fields); 02408 } 02409 else 02410 { 02411 /* 02412 moving from newer mysql to older one -> let's say not an error but 02413 will check the definition afterwards. If a column was added at the 02414 end then we don't care much since it's not in the middle. 02415 */ 02416 error= FALSE; 02417 } 02418 } 02419 //definitely something has changed 02420 char buffer[255]; 02421 for (i=0 ; i < table_f_count; i++, table_def++) 02422 { 02423 String sql_type(buffer, sizeof(buffer), system_charset_info); 02424 sql_type.length(0); 02425 /* 02426 name changes are not fatal, we use sequence numbers => no prob for us 02427 but this can show tampered table or broken table. 02428 */ 02429 if (i < table->s->fields) 02430 { 02431 Field *field= table->field[i]; 02432 if (strncmp(field->field_name, table_def->name.str, 02433 table_def->name.length)) 02434 { 02435 sql_print_error("(%s) Expected field %s at position %d, found %s", 02436 table->alias, table_def->name.str, i, 02437 field->field_name); 02438 } 02439 02440 /* 02441 IF the type does not match than something is really wrong 02442 Check up to length - 1. Why? 02443 1. datetime -> datetim -> the same 02444 2. int(11) -> int(11 -> the same 02445 3. set('one','two') -> set('one','two' 02446 so for sets if the same prefix is there it's ok if more are 02447 added as part of the set. The same is valid for enum. So a new 02448 table running on a old server will be valid. 02449 */ 02450 field->sql_type(sql_type); 02451 if (strncmp(sql_type.c_ptr_safe(), table_def->type.str, 02452 table_def->type.length - 1)) 02453 { 02454 sql_print_error("(%s) Expected field %s at position %d to have type " 02455 "%s, found %s", table->alias, table_def->name.str, 02456 i, table_def->type.str, sql_type.c_ptr_safe()); 02457 error= TRUE; 02458 } 02459 else if (table_def->cset.str && !field->has_charset()) 02460 { 02461 sql_print_error("(%s) Expected field %s at position %d to have " 02462 "character set '%s' but found no such", table->alias, 02463 table_def->name.str, i, table_def->cset.str); 02464 error= TRUE; 02465 } 02466 else if (table_def->cset.str && 02467 strcmp(field->charset()->csname, table_def->cset.str)) 02468 { 02469 sql_print_error("(%s) Expected field %s at position %d to have " 02470 "character set '%s' but found '%s'", table->alias, 02471 table_def->name.str, i, table_def->cset.str, 02472 field->charset()->csname); 02473 error= TRUE; 02474 } 02475 } 02476 else 02477 { 02478 sql_print_error("(%s) Expected field %s at position %d to have type %s " 02479 " but no field found.", table->alias, 02480 table_def->name.str, i, table_def->type.str); 02481 error= TRUE; 02482 } 02483 } 02484 if (!error) 02485 *last_create_time= table->file->stats.create_time; 02486 else if (!fields_diff_count && error_num) 02487 my_error(error_num,MYF(0), table->alias, table_f_count, table->s->fields); 02488 } 02489 else 02490 { 02491 DBUG_PRINT("info", ("Table seems ok without thorough checking.")); 02492 *last_create_time= table->file->stats.create_time; 02493 } 02494 02495 DBUG_RETURN(error); 02496 } 02497 02498 02499 /* 02500 Create Item_field for each column in the table. 02501 02502 SYNPOSIS 02503 st_table::fill_item_list() 02504 item_list a pointer to an empty list used to store items 02505 02506 DESCRIPTION 02507 Create Item_field object for each column in the table and 02508 initialize it with the corresponding Field. New items are 02509 created in the current THD memory root. 02510 02511 RETURN VALUE 02512 0 success 02513 1 out of memory 02514 */ 02515 02516 bool st_table::fill_item_list(List<Item> *item_list) const 02517 { 02518 /* 02519 All Item_field's created using a direct pointer to a field 02520 are fixed in Item_field constructor. 02521 */ 02522 for (Field **ptr= field; *ptr; ptr++) 02523 { 02524 Item_field *item= new Item_field(*ptr); 02525 if (!item || item_list->push_back(item)) 02526 return TRUE; 02527 } 02528 return FALSE; 02529 } 02530 02531 /* 02532 Reset an existing list of Item_field items to point to the 02533 Fields of this table. 02534 02535 SYNPOSIS 02536 st_table::fill_item_list() 02537 item_list a non-empty list with Item_fields 02538 02539 DESCRIPTION 02540 This is a counterpart of fill_item_list used to redirect 02541 Item_fields to the fields of a newly created table. 02542 The caller must ensure that number of items in the item_list 02543 is the same as the number of columns in the table. 02544 */ 02545 02546 void st_table::reset_item_list(List<Item> *item_list) const 02547 { 02548 List_iterator_fast<Item> it(*item_list); 02549 for (Field **ptr= field; *ptr; ptr++) 02550 { 02551 Item_field *item_field= (Item_field*) it++; 02552 DBUG_ASSERT(item_field != 0); 02553 item_field->reset_field(*ptr); 02554 } 02555 } 02556 02557 /* 02558 calculate md5 of query 02559 02560 SYNOPSIS 02561 st_table_list::calc_md5() 02562 buffer buffer for md5 writing 02563 */ 02564 02565 void st_table_list::calc_md5(char *buffer) 02566 { 02567 my_MD5_CTX context; 02568 uchar digest[16]; 02569 my_MD5Init(&context); 02570 my_MD5Update(&context,(uchar *) query.str, query.length); 02571 my_MD5Final(digest, &context); 02572 sprintf((char *) buffer, 02573 "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 02574 digest[0], digest[1], digest[2], digest[3], 02575 digest[4], digest[5], digest[6], digest[7], 02576 digest[8], digest[9], digest[10], digest[11], 02577 digest[12], digest[13], digest[14], digest[15]); 02578 } 02579 02580 02581 /* 02582 set underlying TABLE for table place holder of VIEW 02583 02584 DESCRIPTION 02585 Replace all views that only uses one table with the table itself. 02586 This allows us to treat the view as a simple table and even update 02587 it (it is a kind of optimisation) 02588 02589 SYNOPSIS 02590 st_table_list::set_underlying_merge() 02591 */ 02592 02593 void st_table_list::set_underlying_merge() 02594 { 02595 TABLE_LIST *tbl; 02596 02597 if ((tbl= merge_underlying_list)) 02598 { 02599 /* This is a view. Process all tables of view */ 02600 DBUG_ASSERT(view && effective_algorithm == VIEW_ALGORITHM_MERGE); 02601 do 02602 { 02603 if (tbl->merge_underlying_list) // This is a view 02604 { 02605 DBUG_ASSERT(tbl->view && 02606 tbl->effective_algorithm == VIEW_ALGORITHM_MERGE); 02607 /* 02608 This is the only case where set_ancestor is called on an object 02609 that may not be a view (in which case ancestor is 0) 02610 */ 02611 tbl->merge_underlying_list->set_underlying_merge(); 02612 } 02613 } while ((tbl= tbl->next_local)); 02614 02615 if (!multitable_view) 02616 { 02617 table= merge_underlying_list->table; 02618 schema_table= merge_underlying_list->schema_table; 02619 } 02620 } 02621 } 02622 02623 02624 /* 02625 setup fields of placeholder of merged VIEW 02626 02627 SYNOPSIS 02628 st_table_list::setup_underlying() 02629 thd - thread handler 02630 02631 DESCRIPTION 02632 It is: 02633 - preparing translation table for view columns 02634 If there are underlying view(s) procedure first will be called for them. 02635 02636 RETURN 02637 FALSE - OK 02638 TRUE - error 02639 */ 02640 02641 bool st_table_list::setup_underlying(THD *thd) 02642 { 02643 DBUG_ENTER("st_table_list::setup_underlying"); 02644 02645 if (!field_translation && merge_underlying_list) 02646 { 02647 Field_translator *transl; 02648 SELECT_LEX *select= &view->select_lex; 02649 Item *item; 02650 TABLE_LIST *tbl; 02651 List_iterator_fast<Item> it(select->item_list); 02652 uint field_count= 0; 02653 02654 if (check_stack_overrun(thd, STACK_MIN_SIZE, (char *)&field_count)) 02655 { 02656 DBUG_RETURN(TRUE); 02657 } 02658 02659 for (tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 02660 { 02661 if (tbl->merge_underlying_list && 02662 tbl->setup_underlying(thd)) 02663 { 02664 DBUG_RETURN(TRUE); 02665 } 02666 } 02667 02668 /* Create view fields translation table */ 02669 02670 if (!(transl= 02671 (Field_translator*)(thd->stmt_arena-> 02672 alloc(select->item_list.elements * 02673 sizeof(Field_translator))))) 02674 { 02675 DBUG_RETURN(TRUE); 02676 } 02677 02678 while ((item= it++)) 02679 { 02680 transl[field_count].name= item->name; 02681 transl[field_count++].item= item; 02682 } 02683 field_translation= transl; 02684 field_translation_end= transl + field_count; 02685 /* TODO: use hash for big number of fields */ 02686 02687 /* full text function moving to current select */ 02688 if (view->select_lex.ftfunc_list->elements) 02689 { 02690 Item_func_match *ifm; 02691 SELECT_LEX *current_select= thd->lex->current_select; 02692 List_iterator_fast<Item_func_match> 02693 li(*(view->select_lex.ftfunc_list)); 02694 while ((ifm= li++)) 02695 current_select->ftfunc_list->push_front(ifm); 02696 } 02697 } 02698 DBUG_RETURN(FALSE); 02699 } 02700 02701 02702 /* 02703 Prepare where expression of view 02704 02705 SYNOPSIS 02706 st_table_list::prep_where() 02707 thd - thread handler 02708 conds - condition of this JOIN 02709 no_where_clause - do not build WHERE or ON outer qwery do not need it 02710 (it is INSERT), we do not need conds if this flag is set 02711 02712 NOTE: have to be called befor CHECK OPTION preparation, because it makes 02713 fix_fields for view WHERE clause 02714 02715 RETURN 02716 FALSE - OK 02717 TRUE - error 02718 */ 02719 02720 bool st_table_list::prep_where(THD *thd, Item **conds, 02721 bool no_where_clause) 02722 { 02723 DBUG_ENTER("st_table_list::prep_where"); 02724 02725 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 02726 { 02727 if (tbl->view && tbl->prep_where(thd, conds, no_where_clause)) 02728 { 02729 DBUG_RETURN(TRUE); 02730 } 02731 } 02732 02733 if (where) 02734 { 02735 if (!where->fixed && where->fix_fields(thd, &where)) 02736 { 02737 DBUG_RETURN(TRUE); 02738 } 02739 02740 /* 02741 check that it is not VIEW in which we insert with INSERT SELECT 02742 (in this case we can't add view WHERE condition to main SELECT_LEX) 02743 */ 02744 if (!no_where_clause && !where_processed) 02745 { 02746 TABLE_LIST *tbl= this; 02747 Query_arena *arena= thd->stmt_arena, backup; 02748 arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test 02749 02750 /* Go up to join tree and try to find left join */ 02751 for (; tbl; tbl= tbl->embedding) 02752 { 02753 if (tbl->outer_join) 02754 { 02755 /* 02756 Store WHERE condition to ON expression for outer join, because 02757 we can't use WHERE to correctly execute left joins on VIEWs and 02758 this expression will not be moved to WHERE condition (i.e. will 02759 be clean correctly for PS/SP) 02760 */ 02761 tbl->on_expr= and_conds(tbl->on_expr, where); 02762 break; 02763 } 02764 } 02765 if (tbl == 0) 02766 *conds= and_conds(*conds, where); 02767 if (arena) 02768 thd->restore_active_arena(arena, &backup); 02769 where_processed= TRUE; 02770 } 02771 } 02772 02773 DBUG_RETURN(FALSE); 02774 } 02775 02776 02777 /* 02778 Prepare check option expression of table 02779 02780 SYNOPSIS 02781 st_table_list::prep_check_option() 02782 thd - thread handler 02783 check_opt_type - WITH CHECK OPTION type (VIEW_CHECK_NONE, 02784 VIEW_CHECK_LOCAL, VIEW_CHECK_CASCADED) 02785 we use this parameter instead of direct check of 02786 effective_with_check to change type of underlying 02787 views to VIEW_CHECK_CASCADED if outer view have 02788 such option and prevent processing of underlying 02789 view check options if outer view have just 02790 VIEW_CHECK_LOCAL option. 02791 02792 NOTE 02793 This method build check options for every call 02794 (usual execution or every SP/PS call) 02795 This method have to be called after WHERE preparation 02796 (st_table_list::prep_where) 02797 02798 RETURN 02799 FALSE - OK 02800 TRUE - error 02801 */ 02802 02803 bool st_table_list::prep_check_option(THD *thd, uint8 check_opt_type) 02804 { 02805 DBUG_ENTER("st_table_list::prep_check_option"); 02806 02807 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 02808 { 02809 /* see comment of check_opt_type parameter */ 02810 if (tbl->view && 02811 tbl->prep_check_option(thd, 02812 ((check_opt_type == VIEW_CHECK_CASCADED) ? 02813 VIEW_CHECK_CASCADED : 02814 VIEW_CHECK_NONE))) 02815 { 02816 DBUG_RETURN(TRUE); 02817 } 02818 } 02819 02820 if (check_opt_type) 02821 { 02822 Item *item= 0; 02823 if (where) 02824 { 02825 DBUG_ASSERT(where->fixed); 02826 item= where->copy_andor_structure(thd); 02827 } 02828 if (check_opt_type == VIEW_CHECK_CASCADED) 02829 { 02830 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 02831 { 02832 if (tbl->check_option) 02833 item= and_conds(item, tbl->check_option); 02834 } 02835 } 02836 if (item) 02837 thd->change_item_tree(&check_option, item); 02838 } 02839 02840 if (check_option) 02841 { 02842 const char *save_where= thd->where; 02843 thd->where= "check option"; 02844 if (!check_option->fixed && 02845 check_option->fix_fields(thd, &check_option) || 02846 check_option->check_cols(1)) 02847 { 02848 DBUG_RETURN(TRUE); 02849 } 02850 thd->where= save_where; 02851 } 02852 DBUG_RETURN(FALSE); 02853 } 02854 02855 02856 /* 02857 Hide errors which show view underlying table information 02858 02859 SYNOPSIS 02860 st_table_list::hide_view_error() 02861 thd thread handler 02862 02863 */ 02864 02865 void st_table_list::hide_view_error(THD *thd) 02866 { 02867 /* Hide "Unknown column" or "Unknown function" error */ 02868 if (thd->net.last_errno == ER_BAD_FIELD_ERROR || 02869 thd->net.last_errno == ER_SP_DOES_NOT_EXIST || 02870 thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR || 02871 thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR || 02872 thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR) 02873 { 02874 TABLE_LIST *top= top_table(); 02875 thd->clear_error(); 02876 my_error(ER_VIEW_INVALID, MYF(0), top->view_db.str, top->view_name.str); 02877 } 02878 else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD) 02879 { 02880 TABLE_LIST *top= top_table(); 02881 thd->clear_error(); 02882 // TODO: make correct error message 02883 my_error(ER_NO_DEFAULT_FOR_VIEW_FIELD, MYF(0), 02884 top->view_db.str, top->view_name.str); 02885 } 02886 } 02887 02888 02889 /* 02890 Find underlying base tables (TABLE_LIST) which represent given 02891 table_to_find (TABLE) 02892 02893 SYNOPSIS 02894 st_table_list::find_underlying_table() 02895 table_to_find table to find 02896 02897 RETURN 02898 0 table is not found 02899 found table reference 02900 */ 02901 02902 st_table_list *st_table_list::find_underlying_table(TABLE *table_to_find) 02903 { 02904 /* is this real table and table which we are looking for? */ 02905 if (table == table_to_find && merge_underlying_list == 0) 02906 return this; 02907 02908 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 02909 { 02910 TABLE_LIST *result; 02911 if ((result= tbl->find_underlying_table(table_to_find))) 02912 return result; 02913 } 02914 return 0; 02915 } 02916 02917 /* 02918 cleunup items belonged to view fields translation table 02919 02920 SYNOPSIS 02921 st_table_list::cleanup_items() 02922 */ 02923 02924 void st_table_list::cleanup_items() 02925 { 02926 if (!field_translation) 02927 return; 02928 02929 for (Field_translator *transl= field_translation; 02930 transl < field_translation_end; 02931 transl++) 02932 transl->item->walk(&Item::cleanup_processor, 0, 0); 02933 } 02934 02935 02936 /* 02937 check CHECK OPTION condition 02938 02939 SYNOPSIS 02940 check_option() 02941 ignore_failure ignore check option fail 02942 02943 RETURN 02944 VIEW_CHECK_OK OK 02945 VIEW_CHECK_ERROR FAILED 02946 VIEW_CHECK_SKIP FAILED, but continue 02947 */ 02948 02949 int st_table_list::view_check_option(THD *thd, bool ignore_failure) 02950 { 02951 if (check_option && check_option->val_int() == 0) 02952 { 02953 TABLE_LIST *view= top_table(); 02954 if (ignore_failure) 02955 { 02956 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, 02957 ER_VIEW_CHECK_FAILED, ER(ER_VIEW_CHECK_FAILED), 02958 view->view_db.str, view->view_name.str); 02959 return(VIEW_CHECK_SKIP); 02960 } 02961 else 02962 { 02963 my_error(ER_VIEW_CHECK_FAILED, MYF(0), view->view_db.str, view->view_name.str); 02964 return(VIEW_CHECK_ERROR); 02965 } 02966 } 02967 return(VIEW_CHECK_OK); 02968 } 02969 02970 02971 /* 02972 Find table in underlying tables by mask and check that only this 02973 table belong to given mask 02974 02975 SYNOPSIS 02976 st_table_list::check_single_table() 02977 table reference on variable where to store found table 02978 (should be 0 on call, to find table, or point to table for 02979 unique test) 02980 map bit mask of tables 02981 view view for which we are looking table 02982 02983 RETURN 02984 FALSE table not found or found only one 02985 TRUE found several tables 02986 */ 02987 02988 bool st_table_list::check_single_table(st_table_list **table, table_map map, 02989 st_table_list *view) 02990 { 02991 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 02992 { 02993 if (tbl->table) 02994 { 02995 if (tbl->table->map & map) 02996 { 02997 if (*table) 02998 return TRUE; 02999 *table= tbl; 03000 tbl->check_option= view->check_option; 03001 } 03002 } 03003 else if (tbl->check_single_table(table, map, view)) 03004 return TRUE; 03005 } 03006 return FALSE; 03007 } 03008 03009 03010 /* 03011 Set insert_values buffer 03012 03013 SYNOPSIS 03014 set_insert_values() 03015 mem_root memory pool for allocating 03016 03017 RETURN 03018 FALSE - OK 03019 TRUE - out of memory 03020 */ 03021 03022 bool st_table_list::set_insert_values(MEM_ROOT *mem_root) 03023 { 03024 if (table) 03025 { 03026 if (!table->insert_values && 03027 !(table->insert_values= (byte *)alloc_root(mem_root, 03028 table->s->rec_buff_length))) 03029 return TRUE; 03030 } 03031 else 03032 { 03033 DBUG_ASSERT(view && merge_underlying_list); 03034 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 03035 if (tbl->set_insert_values(mem_root)) 03036 return TRUE; 03037 } 03038 return FALSE; 03039 } 03040 03041 03042 /* 03043 Test if this is a leaf with respect to name resolution. 03044 03045 SYNOPSIS 03046 st_table_list::is_leaf_for_name_resolution() 03047 03048 DESCRIPTION 03049 A table reference is a leaf with respect to name resolution if 03050 it is either a leaf node in a nested join tree (table, view, 03051 schema table, subquery), or an inner node that represents a 03052 NATURAL/USING join, or a nested join with materialized join 03053 columns. 03054 03055 RETURN 03056 TRUE if a leaf, FALSE otherwise. 03057 */ 03058 bool st_table_list::is_leaf_for_name_resolution() 03059 { 03060 return (view || is_natural_join || is_join_columns_complete || 03061 !nested_join); 03062 } 03063 03064 03065 /* 03066 Retrieve the first (left-most) leaf in a nested join tree with 03067 respect to name resolution. 03068 03069 SYNOPSIS 03070 st_table_list::first_leaf_for_name_resolution() 03071 03072 DESCRIPTION 03073 Given that 'this' is a nested table reference, recursively walk 03074 down the left-most children of 'this' until we reach a leaf 03075 table reference with respect to name resolution. 03076 03077 IMPLEMENTATION 03078 The left-most child of a nested table reference is the last element 03079 in the list of children because the children are inserted in 03080 reverse order. 03081 03082 RETURN 03083 If 'this' is a nested table reference - the left-most child of 03084 the tree rooted in 'this', 03085 else return 'this' 03086 */ 03087 03088 TABLE_LIST *st_table_list::first_leaf_for_name_resolution() 03089 { 03090 TABLE_LIST *cur_table_ref; 03091 NESTED_JOIN *cur_nested_join; 03092 LINT_INIT(cur_table_ref); 03093 03094 if (is_leaf_for_name_resolution()) 03095 return this; 03096 DBUG_ASSERT(nested_join); 03097 03098 for (cur_nested_join= nested_join; 03099 cur_nested_join; 03100 cur_nested_join= cur_table_ref->nested_join) 03101 { 03102 List_iterator_fast<TABLE_LIST> it(cur_nested_join->join_list); 03103 cur_table_ref= it++; 03104 /* 03105 If the current nested join is a RIGHT JOIN, the operands in 03106 'join_list' are in reverse order, thus the first operand is 03107 already at the front of the list. Otherwise the first operand 03108 is in the end of the list of join operands. 03109 */ 03110 if (!(cur_table_ref->outer_join & JOIN_TYPE_RIGHT)) 03111 { 03112 TABLE_LIST *next; 03113 while ((next= it++)) 03114 cur_table_ref= next; 03115 } 03116 if (cur_table_ref->is_leaf_for_name_resolution()) 03117 break; 03118 } 03119 return cur_table_ref; 03120 } 03121 03122 03123 /* 03124 Retrieve the last (right-most) leaf in a nested join tree with 03125 respect to name resolution. 03126 03127 SYNOPSIS 03128 st_table_list::last_leaf_for_name_resolution() 03129 03130 DESCRIPTION 03131 Given that 'this' is a nested table reference, recursively walk 03132 down the right-most children of 'this' until we reach a leaf 03133 table reference with respect to name resolution. 03134 03135 IMPLEMENTATION 03136 The right-most child of a nested table reference is the first 03137 element in the list of children because the children are inserted 03138 in reverse order. 03139 03140 RETURN 03141 - If 'this' is a nested table reference - the right-most child of 03142 the tree rooted in 'this', 03143 - else - 'this' 03144 */ 03145 03146 TABLE_LIST *st_table_list::last_leaf_for_name_resolution() 03147 { 03148 TABLE_LIST *cur_table_ref= this; 03149 NESTED_JOIN *cur_nested_join; 03150 03151 if (is_leaf_for_name_resolution()) 03152 return this; 03153 DBUG_ASSERT(nested_join); 03154 03155 for (cur_nested_join= nested_join; 03156 cur_nested_join; 03157 cur_nested_join= cur_table_ref->nested_join) 03158 { 03159 cur_table_ref= cur_nested_join->join_list.head(); 03160 /* 03161 If the current nested is a RIGHT JOIN, the operands in 03162 'join_list' are in reverse order, thus the last operand is in the 03163 end of the list. 03164 */ 03165 if ((cur_table_ref->outer_join & JOIN_TYPE_RIGHT)) 03166 { 03167 List_iterator_fast<TABLE_LIST> it(cur_nested_join->join_list); 03168 TABLE_LIST *next; 03169 cur_table_ref= it++; 03170 while ((next= it++)) 03171 cur_table_ref= next; 03172 } 03173 if (cur_table_ref->is_leaf_for_name_resolution()) 03174 break; 03175 } 03176 return cur_table_ref; 03177 } 03178 03179 03180 /* 03181 Register access mode which we need for underlying tables 03182 03183 SYNOPSIS 03184 register_want_access() 03185 want_access Acess which we require 03186 */ 03187 03188 void st_table_list::register_want_access(ulong want_access) 03189 { 03190 /* Remove SHOW_VIEW_ACL, because it will be checked during making view */ 03191 want_access&= ~SHOW_VIEW_ACL; 03192 if (belong_to_view) 03193 { 03194 grant.want_privilege= want_access; 03195 if (table) 03196 table->grant.want_privilege= want_access; 03197 } 03198 for (TABLE_LIST *tbl= merge_underlying_list; tbl; tbl= tbl->next_local) 03199 tbl->register_want_access(want_access); 03200 } 03201 03202 03203 /* 03204 Load security context information for this view 03205 03206 SYNOPSIS 03207 st_table_list::prepare_view_securety_context() 03208 thd [in] thread handler 03209 03210 RETURN 03211 FALSE OK 03212 TRUE Error 03213 */ 03214 03215 #ifndef NO_EMBEDDED_ACCESS_CHECKS 03216 bool st_table_list::prepare_view_securety_context(THD *thd) 03217 { 03218 DBUG_ENTER("st_table_list::prepare_view_securety_context"); 03219 DBUG_PRINT("enter", ("table: %s", alias)); 03220 03221 DBUG_ASSERT(!prelocking_placeholder && view); 03222 if (view_suid) 03223 { 03224 DBUG_PRINT("info", ("This table is suid view => load contest")); 03225 DBUG_ASSERT(view && view_sctx); 03226 if (acl_getroot_no_password(view_sctx, 03227 definer.user.str, 03228 definer.host.str, 03229 definer.host.str, 03230 thd->db)) 03231 { 03232 if (thd->lex->sql_command == SQLCOM_SHOW_CREATE) 03233 { 03234 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 03235 ER_NO_SUCH_USER, 03236 ER(ER_NO_SUCH_USER), 03237 definer.user.str, definer.host.str); 03238 } 03239 else 03240 { 03241 my_error(ER_NO_SUCH_USER, MYF(0), definer.user.str, definer.host.str); 03242 DBUG_RETURN(TRUE); 03243 } 03244 } 03245 } 03246 DBUG_RETURN(FALSE); 03247 } 03248 #endif 03249 03250 03251 /* 03252 Find security context of current view 03253 03254 SYNOPSIS 03255 st_table_list::find_view_security_context() 03256 thd [in] thread handler 03257 03258 */ 03259 03260 #ifndef NO_EMBEDDED_ACCESS_CHECKS 03261 Security_context *st_table_list::find_view_security_context(THD *thd) 03262 { 03263 Security_context *sctx; 03264 TABLE_LIST *upper_view= this; 03265 DBUG_ENTER("st_table_list::find_view_security_context"); 03266 03267 DBUG_ASSERT(view); 03268 while (upper_view && !upper_view->view_suid) 03269 { 03270 DBUG_ASSERT(!upper_view->prelocking_placeholder); 03271 upper_view= upper_view->referencing_view; 03272 } 03273 if (upper_view) 03274 { 03275 DBUG_PRINT("info", ("Securety context of view %s will be used", 03276 upper_view->alias)); 03277 sctx= upper_view->view_sctx; 03278 DBUG_ASSERT(sctx); 03279 } 03280 else 03281 { 03282 DBUG_PRINT("info", ("Current global context will be used")); 03283 sctx= thd->security_ctx; 03284 } 03285 DBUG_RETURN(sctx); 03286 } 03287 #endif 03288 03289 03290 /* 03291 Prepare security context and load underlying tables priveleges for view 03292 03293 SYNOPSIS 03294 st_table_list::prepare_security() 03295 thd [in] thread handler 03296 03297 RETURN 03298 FALSE OK 03299 TRUE Error 03300 */ 03301 03302 bool st_table_list::prepare_security(THD *thd) 03303 { 03304 List_iterator_fast<TABLE_LIST> tb(*view_tables); 03305 TABLE_LIST *tbl; 03306 DBUG_ENTER("st_table_list::prepare_security"); 03307 #ifndef NO_EMBEDDED_ACCESS_CHECKS 03308 Security_context *save_security_ctx= thd->security_ctx; 03309 03310 DBUG_ASSERT(!prelocking_placeholder); 03311 if (prepare_view_securety_context(thd)) 03312 DBUG_RETURN(TRUE); 03313 thd->security_ctx= find_view_security_context(thd); 03314 while ((tbl= tb++)) 03315 { 03316 DBUG_ASSERT(tbl->referencing_view); 03317 char *db, *table_name; 03318 if (tbl->view) 03319 { 03320 db= tbl->view_db.str; 03321 table_name= tbl->view_name.str; 03322 } 03323 else 03324 { 03325 db= tbl->db; 03326 table_name= tbl->table_name; 03327 } 03328 fill_effective_table_privileges(thd, &tbl->grant, db, table_name); 03329 if (tbl->table) 03330 tbl->table->grant= grant; 03331 } 03332 thd->security_ctx= save_security_ctx; 03333 #else 03334 while ((tbl= tb++)) 03335 tbl->grant.privilege= ~NO_ACCESS; 03336 #endif 03337 DBUG_RETURN(FALSE); 03338 } 03339 03340 03341 Natural_join_column::Natural_join_column(Field_translator *field_param, 03342 TABLE_LIST *tab) 03343 { 03344 DBUG_ASSERT(tab->field_translation); 03345 view_field= field_param; 03346 table_field= NULL; 03347 table_ref= tab; 03348 is_common= FALSE; 03349 } 03350 03351 03352 Natural_join_column::Natural_join_column(Field *field_param, 03353 TABLE_LIST *tab) 03354 { 03355 DBUG_ASSERT(tab->table == field_param->table); 03356 table_field= field_param; 03357 view_field= NULL; 03358 table_ref= tab; 03359 is_common= FALSE; 03360 } 03361 03362 03363 const char *Natural_join_column::name() 03364 { 03365 if (view_field) 03366 { 03367 DBUG_ASSERT(table_field == NULL); 03368 return view_field->name; 03369 } 03370 03371 return table_field->field_name; 03372 } 03373 03374 03375 Item *Natural_join_column::create_item(THD *thd) 03376 { 03377 if (view_field) 03378 { 03379 DBUG_ASSERT(table_field == NULL); 03380 return create_view_field(thd, table_ref, &view_field->item, 03381 view_field->name); 03382 } 03383 return new Item_field(thd, &thd->lex->current_select->context, table_field); 03384 } 03385 03386 03387 Field *Natural_join_column::field() 03388 { 03389 if (view_field) 03390 { 03391 DBUG_ASSERT(table_field == NULL); 03392 return NULL; 03393 } 03394 return table_field; 03395 } 03396 03397 03398 const char *Natural_join_column::table_name() 03399 { 03400 return table_ref->alias; 03401 } 03402 03403 03404 const char *Natural_join_column::db_name() 03405 { 03406 if (view_field) 03407 return table_ref->view_db.str; 03408 03409 /* 03410 Test that TABLE_LIST::db is the same as st_table_share::db to 03411 ensure consistency. An exception are I_S schema tables, which 03412 are inconsistent in this respect. 03413 */ 03414 DBUG_ASSERT(!strcmp(table_ref->db, 03415 table_ref->table->s->db.str) || 03416 (table_ref->schema_table && 03417 table_ref->table->s->db.str[0] == 0)); 03418 return table_ref->db; 03419 } 03420 03421 03422 GRANT_INFO *Natural_join_column::grant() 03423 { 03424 if (view_field) 03425 return &(table_ref->grant); 03426 return &(table_ref->table->grant); 03427 } 03428 03429 03430 void Field_iterator_view::set(TABLE_LIST *table) 03431 { 03432 DBUG_ASSERT(table->field_translation); 03433 view= table; 03434 ptr= table->field_translation; 03435 array_end= table->field_translation_end; 03436 } 03437 03438 03439 const char *Field_iterator_table::name() 03440 { 03441 return (*ptr)->field_name; 03442 } 03443 03444 03445 Item *Field_iterator_table::create_item(THD *thd) 03446 { 03447 return new Item_field(thd, &thd->lex->current_select->context, *ptr); 03448 } 03449 03450 03451 const char *Field_iterator_view::name() 03452 { 03453 return ptr->name; 03454 } 03455 03456 03457 Item *Field_iterator_view::create_item(THD *thd) 03458 { 03459 return create_view_field(thd, view, &ptr->item, ptr->name); 03460 } 03461 03462 Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref, 03463 const char *name) 03464 { 03465 bool save_wrapper= thd->lex->select_lex.no_wrap_view_item; 03466 Item *field= *field_ref; 03467 DBUG_ENTER("create_view_field"); 03468 03469 if (view->schema_table_reformed) 03470 { 03471 /* 03472 Translation table items are always Item_fields and already fixed 03473 ('mysql_schema_table' function). So we can return directly the 03474 field. This case happens only for 'show & where' commands. 03475 */ 03476 DBUG_ASSERT(field && field->fixed); 03477 DBUG_RETURN(field); 03478 } 03479 03480 DBUG_ASSERT(field); 03481 thd->lex->current_select->no_wrap_view_item= TRUE; 03482 if (!field->fixed) 03483 { 03484 if (field->fix_fields(thd, field_ref)) 03485 { 03486 thd->lex->current_select->no_wrap_view_item= save_wrapper; 03487 DBUG_RETURN(0); 03488 } 03489 field= *field_ref; 03490 } 03491 thd->lex->current_select->no_wrap_view_item= save_wrapper; 03492 if (save_wrapper) 03493 { 03494 DBUG_RETURN(field); 03495 } 03496 Item *item= new Item_direct_view_ref(&view->view->select_lex.context, 03497 field_ref, view->alias, 03498 name); 03499 DBUG_RETURN(item); 03500 } 03501 03502 03503 void Field_iterator_natural_join::set(TABLE_LIST *table_ref) 03504 { 03505 DBUG_ASSERT(table_ref->join_columns); 03506 column_ref_it.init(*(table_ref->join_columns)); 03507 cur_column_ref= column_ref_it++; 03508 } 03509 03510 03511 void Field_iterator_natural_join::next() 03512 { 03513 cur_column_ref= column_ref_it++; 03514 DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || 03515 cur_column_ref->table_ref->table == 03516 cur_column_ref->table_field->table); 03517 } 03518 03519 03520 void Field_iterator_table_ref::set_field_iterator() 03521 { 03522 DBUG_ENTER("Field_iterator_table_ref::set_field_iterator"); 03523 /* 03524 If the table reference we are iterating over is a natural join, or it is 03525 an operand of a natural join, and TABLE_LIST::join_columns contains all 03526 the columns of the join operand, then we pick the columns from 03527 TABLE_LIST::join_columns, instead of the orginial container of the 03528 columns of the join operator. 03529 */ 03530 if (table_ref->is_join_columns_complete) 03531 { 03532 /* Necesary, but insufficient conditions. */ 03533 DBUG_ASSERT(table_ref->is_natural_join || 03534 table_ref->nested_join || 03535 table_ref->join_columns && 03536 /* This is a merge view. */ 03537 ((table_ref->field_translation && 03538 table_ref->join_columns->elements == 03539 (ulong)(table_ref->field_translation_end - 03540 table_ref->field_translation)) || 03541 /* This is stored table or a tmptable view. */ 03542 (!table_ref->field_translation && 03543 table_ref->join_columns->elements == 03544 table_ref->table->s->fields))); 03545 field_it= &natural_join_it; 03546 DBUG_PRINT("info",("field_it for '%s' is Field_iterator_natural_join", 03547 table_ref->alias)); 03548 } 03549 /* This is a merge view, so use field_translation. */ 03550 else if (table_ref->field_translation) 03551 { 03552 DBUG_ASSERT(table_ref->view && 03553 table_ref->effective_algorithm == VIEW_ALGORITHM_MERGE); 03554 field_it= &view_field_it; 03555 DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_view", 03556 table_ref->alias)); 03557 } 03558 /* This is a base table or stored view. */ 03559 else 03560 { 03561 DBUG_ASSERT(table_ref->table || table_ref->view); 03562 field_it= &table_field_it; 03563 DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_table", 03564 table_ref->alias)); 03565 } 03566 field_it->set(table_ref); 03567 DBUG_VOID_RETURN; 03568 } 03569 03570 03571 void Field_iterator_table_ref::set(TABLE_LIST *table) 03572 { 03573 DBUG_ASSERT(table); 03574 first_leaf= table->first_leaf_for_name_resolution(); 03575 last_leaf= table->last_leaf_for_name_resolution(); 03576 DBUG_ASSERT(first_leaf && last_leaf); 03577 table_ref= first_leaf; 03578 set_field_iterator(); 03579 } 03580 03581 03582 void Field_iterator_table_ref::next() 03583 { 03584 /* Move to the next field in the current table reference. */ 03585 field_it->next(); 03586 /* 03587 If all fields of the current table reference are exhausted, move to 03588 the next leaf table reference. 03589 */ 03590 if (field_it->end_of_fields() && table_ref != last_leaf) 03591 { 03592 table_ref= table_ref->next_name_resolution_table; 03593 DBUG_ASSERT(table_ref); 03594 set_field_iterator(); 03595 } 03596 } 03597 03598 03599 const char *Field_iterator_table_ref::table_name() 03600 { 03601 if (table_ref->view) 03602 return table_ref->view_name.str; 03603 else if (table_ref->is_natural_join) 03604 return natural_join_it.column_ref()->table_name(); 03605 03606 DBUG_ASSERT(!strcmp(table_ref->table_name, 03607 table_ref->table->s->table_name.str)); 03608 return table_ref->table_name; 03609 } 03610 03611 03612 const char *Field_iterator_table_ref::db_name() 03613 { 03614 if (table_ref->view) 03615 return table_ref->view_db.str; 03616 else if (table_ref->is_natural_join) 03617 return natural_join_it.column_ref()->db_name(); 03618 03619 /* 03620 Test that TABLE_LIST::db is the same as st_table_share::db to 03621 ensure consistency. An exception are I_S schema tables, which 03622 are inconsistent in this respect. 03623 */ 03624 DBUG_ASSERT(!strcmp(table_ref->db, table_ref->table->s->db.str) || 03625 (table_ref->schema_table && 03626 table_ref->table->s->db.str[0] == 0)); 03627 03628 return table_ref->db; 03629 } 03630 03631 03632 GRANT_INFO *Field_iterator_table_ref::grant() 03633 { 03634 if (table_ref->view) 03635 return &(table_ref->grant); 03636 else if (table_ref->is_natural_join) 03637 return natural_join_it.column_ref()->grant(); 03638 return &(table_ref->table->grant); 03639 } 03640 03641 03642 /* 03643 Create new or return existing column reference to a column of a 03644 natural/using join. 03645 03646 SYNOPSIS 03647 Field_iterator_table_ref::get_or_create_column_ref() 03648 parent_table_ref the parent table reference over which the 03649 iterator is iterating 03650 03651 DESCRIPTION 03652 Create a new natural join column for the current field of the 03653 iterator if no such column was created, or return an already 03654 created natural join column. The former happens for base tables or 03655 views, and the latter for natural/using joins. If a new field is 03656 created, then the field is added to 'parent_table_ref' if it is 03657 given, or to the original table referene of the field if 03658 parent_table_ref == NULL. 03659 03660 NOTES 03661 This method is designed so that when a Field_iterator_table_ref 03662 walks through the fields of a table reference, all its fields 03663 are created and stored as follows: 03664 - If the table reference being iterated is a stored table, view or 03665 natural/using join, store all natural join columns in a list 03666 attached to that table reference. 03667 - If the table reference being iterated is a nested join that is 03668 not natural/using join, then do not materialize its result 03669 fields. This is OK because for such table references 03670 Field_iterator_table_ref iterates over the fields of the nested 03671 table references (recursively). In this way we avoid the storage 03672 of unnecessay copies of result columns of nested joins. 03673 03674 RETURN 03675 # Pointer to a column of a natural join (or its operand) 03676 NULL No memory to allocate the column 03677 */ 03678 03679 Natural_join_column * 03680 Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) 03681 { 03682 Natural_join_column *nj_col; 03683 bool is_created= TRUE; 03684 uint field_count; 03685 TABLE_LIST *add_table_ref= parent_table_ref ? 03686 parent_table_ref : table_ref; 03687 03688 LINT_INIT(field_count); 03689 if (field_it == &table_field_it) 03690 { 03691 /* The field belongs to a stored table. */ 03692 Field *field= table_field_it.field(); 03693 nj_col= new Natural_join_column(field, table_ref); 03694 field_count= table_ref->table->s->fields; 03695 } 03696 else if (field_it == &view_field_it) 03697 { 03698 /* The field belongs to a merge view or information schema table. */ 03699 Field_translator *translated_field= view_field_it.field_translator(); 03700 nj_col= new Natural_join_column(translated_field, table_ref); 03701 field_count= table_ref->field_translation_end - 03702 table_ref->field_translation; 03703 } 03704 else 03705 { 03706 /* 03707 The field belongs to a NATURAL join, therefore the column reference was 03708 already created via one of the two constructor calls above. In this case 03709 we just return the already created column reference. 03710 */ 03711 DBUG_ASSERT(table_ref->is_join_columns_complete); 03712 is_created= FALSE; 03713 nj_col= natural_join_it.column_ref(); 03714 DBUG_ASSERT(nj_col); 03715 } 03716 DBUG_ASSERT(!nj_col->table_field || 03717 nj_col->table_ref->table == nj_col->table_field->table); 03718 03719 /* 03720 If the natural join column was just created add it to the list of 03721 natural join columns of either 'parent_table_ref' or to the table 03722 reference that directly contains the original field. 03723 */ 03724 if (is_created) 03725 { 03726 /* Make sure not all columns were materialized. */ 03727 DBUG_ASSERT(!add_table_ref->is_join_columns_complete); 03728 if (!add_table_ref->join_columns) 03729 { 03730 /* Create a list of natural join columns on demand. */ 03731 if (!(add_table_ref->join_columns= new List<Natural_join_column>)) 03732 return NULL; 03733 add_table_ref->is_join_columns_complete= FALSE; 03734 } 03735 add_table_ref->join_columns->push_back(nj_col); 03736 /* 03737 If new fields are added to their original table reference, mark if 03738 all fields were added. We do it here as the caller has no easy way 03739 of knowing when to do it. 03740 If the fields are being added to parent_table_ref, then the caller 03741 must take care to mark when all fields are created/added. 03742 */ 03743 if (!parent_table_ref && 03744 add_table_ref->join_columns->elements == field_count) 03745 add_table_ref->is_join_columns_complete= TRUE; 03746 } 03747 03748 return nj_col; 03749 } 03750 03751 03752 /* 03753 Return an existing reference to a column of a natural/using join. 03754 03755 SYNOPSIS 03756 Field_iterator_table_ref::get_natural_column_ref() 03757 03758 DESCRIPTION 03759 The method should be called in contexts where it is expected that 03760 all natural join columns are already created, and that the column 03761 being retrieved is a Natural_join_column. 03762 03763 RETURN 03764 # Pointer to a column of a natural join (or its operand) 03765 NULL No memory to allocate the column 03766 */ 03767 03768 Natural_join_column * 03769 Field_iterator_table_ref::get_natural_column_ref() 03770 { 03771 Natural_join_column *nj_col; 03772 03773 DBUG_ASSERT(field_it == &natural_join_it); 03774 /* 03775 The field belongs to a NATURAL join, therefore the column reference was 03776 already created via one of the two constructor calls above. In this case 03777 we just return the already created column reference. 03778 */ 03779 nj_col= natural_join_it.column_ref(); 03780 DBUG_ASSERT(nj_col && 03781 (!nj_col->table_field || 03782 nj_col->table_ref->table == nj_col->table_field->table)); 03783 return nj_col; 03784 } 03785 03786 /***************************************************************************** 03787 Functions to handle column usage bitmaps (read_set, write_set etc...) 03788 *****************************************************************************/ 03789 03790 /* Reset all columns bitmaps */ 03791 03792 void st_table::clear_column_bitmaps() 03793 { 03794 /* 03795 Reset column read/write usage. It's identical to: 03796 bitmap_clear_all(&table->def_read_set); 03797 bitmap_clear_all(&table->def_write_set); 03798 */ 03799 bzero((char*) def_read_set.bitmap, s->column_bitmap_size*2); 03800 column_bitmaps_set(&def_read_set, &def_write_set); 03801 } 03802 03803 03804 /* 03805 Tell handler we are going to call position() and rnd_pos() later. 03806 03807 NOTES: 03808 This is needed for handlers that uses the primary key to find the 03809 row. In this case we have to extend the read bitmap with the primary 03810 key fields. 03811 */ 03812 03813 void st_table::prepare_for_position() 03814 { 03815 DBUG_ENTER("st_table::prepare_for_position"); 03816 03817 if ((file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && 03818 s->primary_key < MAX_KEY) 03819 { 03820 mark_columns_used_by_index_no_reset(s->primary_key, read_set); 03821 /* signal change */ 03822 file->column_bitmaps_signal(); 03823 } 03824 DBUG_VOID_RETURN; 03825 } 03826 03827 03828 /* 03829 Mark that only fields from one key is used 03830 03831 NOTE: 03832 This changes the bitmap to use the tmp bitmap 03833 After this, you can't access any other columns in the table until 03834 bitmaps are reset, for example with st_table::clear_column_bitmaps() 03835 or st_table::restore_column_maps_after_mark_index() 03836 */ 03837 03838 void st_table::mark_columns_used_by_index(uint index) 03839 { 03840 MY_BITMAP *bitmap= &tmp_set; 03841 DBUG_ENTER("st_table::mark_columns_used_by_index"); 03842 03843 (void) file->extra(HA_EXTRA_KEYREAD); 03844 bitmap_clear_all(bitmap); 03845 mark_columns_used_by_index_no_reset(index, bitmap); 03846 column_bitmaps_set(bitmap, bitmap); 03847 DBUG_VOID_RETURN; 03848 } 03849 03850 03851 /* 03852 Restore to use normal column maps after key read 03853 03854 NOTES 03855 This reverse the change done by mark_columns_used_by_index 03856 03857 WARNING 03858 For this to work, one must have the normal table maps in place 03859 when calling mark_columns_used_by_index 03860 */ 03861 03862 void st_table::restore_column_maps_after_mark_index() 03863 { 03864 DBUG_ENTER("st_table::restore_column_maps_after_mark_index"); 03865 03866 key_read= 0; 03867 (void) file->extra(HA_EXTRA_NO_KEYREAD); 03868 default_column_bitmaps(); 03869 file->column_bitmaps_signal(); 03870 DBUG_VOID_RETURN; 03871 } 03872 03873 03874 /* 03875 mark columns used by key, but don't reset other fields 03876 */ 03877 03878 void st_table::mark_columns_used_by_index_no_reset(uint index, 03879 MY_BITMAP *bitmap) 03880 { 03881 KEY_PART_INFO *key_part= key_info[index].key_part; 03882 KEY_PART_INFO *key_part_end= (key_part + 03883 key_info[index].key_parts); 03884 for (;key_part != key_part_end; key_part++) 03885 bitmap_set_bit(bitmap, key_part->fieldnr-1); 03886 } 03887 03888 03889 /* 03890 Mark auto-increment fields as used fields in both read and write maps 03891 03892 NOTES 03893 This is needed in insert & update as the auto-increment field is 03894 always set and sometimes read. 03895 */ 03896 03897 void st_table::mark_auto_increment_column() 03898 { 03899 DBUG_ASSERT(found_next_number_field); 03900 /* 03901 We must set bit in read set as update_auto_increment() is using the 03902 store() to check overflow of auto_increment values 03903 */ 03904 bitmap_set_bit(read_set, found_next_number_field->field_index); 03905 bitmap_set_bit(write_set, found_next_number_field->field_index); 03906 if (s->next_number_key_offset) 03907 mark_columns_used_by_index_no_reset(s->next_number_index, read_set); 03908 file->column_bitmaps_signal(); 03909 } 03910 03911 03912 /* 03913 Mark columns needed for doing an delete of a row 03914 03915 DESCRIPTON 03916 Some table engines don't have a cursor on the retrieve rows 03917 so they need either to use the primary key or all columns to 03918 be able to delete a row. 03919 03920 If the engine needs this, the function works as follows: 03921 - If primary key exits, mark the primary key columns to be read. 03922 - If not, mark all columns to be read 03923 03924 If the engine has HA_REQUIRES_KEY_COLUMNS_FOR_DELETE, we will 03925 mark all key columns as 'to-be-read'. This allows the engine to 03926 loop over the given record to find all keys and doesn't have to 03927 retrieve the row again. 03928 */ 03929 03930 void st_table::mark_columns_needed_for_delete() 03931 { 03932 if (triggers) 03933 triggers->mark_fields_used(TRG_EVENT_DELETE); 03934 if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE) 03935 { 03936 Field **reg_field; 03937 for (reg_field= field ; *reg_field ; reg_field++) 03938 { 03939 if ((*reg_field)->flags & PART_KEY_FLAG) 03940 bitmap_set_bit(read_set, (*reg_field)->field_index); 03941 } 03942 file->column_bitmaps_signal(); 03943 } 03944 if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) 03945 { 03946 /* 03947 If the handler has no cursor capabilites, we have to read either 03948 the primary key, the hidden primary key or all columns to be 03949 able to do an delete 03950 */ 03951 if (s->primary_key == MAX_KEY) 03952 file->use_hidden_primary_key(); 03953 else 03954 { 03955 mark_columns_used_by_index_no_reset(s->primary_key, read_set); 03956 file->column_bitmaps_signal(); 03957 } 03958 } 03959 } 03960 03961 03962 /* 03963 Mark columns needed for doing an update of a row 03964 03965 DESCRIPTON 03966 Some engines needs to have all columns in an update (to be able to 03967 build a complete row). If this is the case, we mark all not 03968 updated columns to be read. 03969 03970 If this is no the case, we do like in the delete case and mark 03971 if neeed, either the primary key column or all columns to be read. 03972 (see mark_columns_needed_for_delete() for details) 03973 03974 If the engine has HA_REQUIRES_KEY_COLUMNS_FOR_DELETE, we will 03975 mark all USED key columns as 'to-be-read'. This allows the engine to 03976 loop over the given record to find all changed keys and doesn't have to 03977 retrieve the row again. 03978 */ 03979 03980 void st_table::mark_columns_needed_for_update() 03981 { 03982 DBUG_ENTER("mark_columns_needed_for_update"); 03983 if (triggers) 03984 triggers->mark_fields_used(TRG_EVENT_UPDATE); 03985 if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE) 03986 { 03987 /* Mark all used key columns for read */ 03988 Field **reg_field; 03989 for (reg_field= field ; *reg_field ; reg_field++) 03990 { 03991 /* Merge keys is all keys that had a column refered to in the query */ 03992 if (merge_keys.is_overlapping((*reg_field)->part_of_key)) 03993 bitmap_set_bit(read_set, (*reg_field)->field_index); 03994 } 03995 file->column_bitmaps_signal(); 03996 } 03997 if (file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) 03998 { 03999 /* 04000 If the handler has no cursor capabilites, we have to read either 04001 the primary key, the hidden primary key or all columns to be 04002 able to do an update 04003 */ 04004 if (s->primary_key == MAX_KEY) 04005 file->use_hidden_primary_key(); 04006 else 04007 { 04008 mark_columns_used_by_index_no_reset(s->primary_key, read_set); 04009 file->column_bitmaps_signal(); 04010 } 04011 } 04012 DBUG_VOID_RETURN; 04013 } 04014 04015 04016 /* 04017 Mark columns the handler needs for doing an insert 04018 04019 For now, this is used to mark fields used by the trigger 04020 as changed. 04021 */ 04022 04023 void st_table::mark_columns_needed_for_insert() 04024 { 04025 if (triggers) 04026 { 04027 /* 04028 We don't need to mark columns which are used by ON DELETE and 04029 ON UPDATE triggers, which may be invoked in case of REPLACE or 04030 INSERT ... ON DUPLICATE KEY UPDATE, since before doing actual 04031 row replacement or update write_record() will mark all table 04032 fields as used. 04033 */ 04034 triggers->mark_fields_used(TRG_EVENT_INSERT); 04035 } 04036 if (found_next_number_field) 04037 mark_auto_increment_column(); 04038 } 04039 04040 /* 04041 Cleanup this table for re-execution. 04042 04043 SYNOPSIS 04044 st_table_list::reinit_before_use() 04045 */ 04046 04047 void st_table_list::reinit_before_use(THD *thd) 04048 { 04049 /* 04050 Reset old pointers to TABLEs: they are not valid since the tables 04051 were closed in the end of previous prepare or execute call. 04052 */ 04053 table= 0; 04054 /* Reset is_schema_table_processed value(needed for I_S tables */ 04055 is_schema_table_processed= FALSE; 04056 04057 TABLE_LIST *embedded; /* The table at the current level of nesting. */ 04058 TABLE_LIST *embedding= this; /* The parent nested table reference. */ 04059 do 04060 { 04061 embedded= embedding; 04062 if (embedded->prep_on_expr) 04063 embedded->on_expr= embedded->prep_on_expr->copy_andor_structure(thd); 04064 embedding= embedded->embedding; 04065 } 04066 while (embedding && 04067 embedding->nested_join->join_list.head() == embedded); 04068 } 04069 04070 04071 /***************************************************************************** 04072 ** Instansiate templates 04073 *****************************************************************************/ 04074 04075 #ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION 04076 template class List<String>; 04077 template class List_iterator<String>; 04078 #endif
1.4.7

