diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/Makefile.am | 6 | ||||
-rw-r--r-- | sql/examples/ha_archive.cc | 60 | ||||
-rw-r--r-- | sql/examples/ha_archive.h | 4 | ||||
-rw-r--r-- | sql/field.cc | 109 | ||||
-rw-r--r-- | sql/field.h | 4 | ||||
-rw-r--r-- | sql/filesort.cc | 4 | ||||
-rw-r--r-- | sql/ha_federated.cc | 296 | ||||
-rwxr-xr-x | sql/ha_federated.h | 8 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 5 | ||||
-rw-r--r-- | sql/ha_ndbcluster.cc | 77 | ||||
-rw-r--r-- | sql/ha_ndbcluster.h | 1 | ||||
-rw-r--r-- | sql/handler.cc | 14 | ||||
-rw-r--r-- | sql/item_create.cc | 5 | ||||
-rw-r--r-- | sql/item_sum.cc | 6 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 17 | ||||
-rw-r--r-- | sql/key.cc | 4 | ||||
-rw-r--r-- | sql/mysql_priv.h | 9 | ||||
-rw-r--r-- | sql/mysqld.cc | 19 | ||||
-rw-r--r-- | sql/opt_range.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 14 | ||||
-rw-r--r-- | sql/set_var.h | 2 | ||||
-rw-r--r-- | sql/share/Makefile.am | 5 | ||||
-rw-r--r-- | sql/sql_acl.cc | 4 | ||||
-rw-r--r-- | sql/sql_analyse.cc | 40 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_help.cc | 7 | ||||
-rw-r--r-- | sql/sql_insert.cc | 47 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_select.cc | 11 | ||||
-rw-r--r-- | sql/sql_show.cc | 18 | ||||
-rw-r--r-- | sql/table.cc | 6 |
31 files changed, 553 insertions, 254 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am index 8ff55898ba4..3c520ac971c 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -22,7 +22,7 @@ MYSQLBASEdir= $(prefix) INCLUDES = @MT_INCLUDES@ @ZLIB_INCLUDES@ \ @bdb_includes@ @innodb_includes@ @ndbcluster_includes@ \ -I$(top_srcdir)/include -I$(top_srcdir)/regex \ - -I$(srcdir) $(openssl_includes) -I$(top_srcdir)/extra + -I$(srcdir) $(openssl_includes) -I$(top_builddir)/include WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld @@ -115,6 +115,7 @@ DEFS = -DMYSQL_SERVER \ # Don't put lex_hash.h in BUILT_SOURCES as this will give infinite recursion BUILT_SOURCES = sql_yacc.cc sql_yacc.h EXTRA_DIST = udf_example.cc $(BUILT_SOURCES) +DISTCLEANFILES = lex_hash.h AM_YFLAGS = -d mysql_tzinfo_to_sql.cc: @@ -160,8 +161,5 @@ sql_lex.o: lex_hash.h udf_example.so: udf_example.cc $(CXXCOMPILE) -shared -o $@ $< -distclean: - rm -f lex_hash.h - # Don't update the files from bitkeeper %::SCCS/s.% diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index dccff88bf1f..436c72702a0 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -117,7 +117,6 @@ /* Variables for archive share methods */ pthread_mutex_t archive_mutex; static HASH archive_open_tables; -static int archive_init= 0; /* The file extension */ #define ARZ ".ARZ" // The data file @@ -143,6 +142,46 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length, return (byte*) share->table_name; } + +/* + Initialize the archive handler. + + SYNOPSIS + archive_db_init() + void + + RETURN + FALSE OK + TRUE Error +*/ + +bool archive_db_init() +{ + VOID(pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST)); + return (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0, + (hash_get_key) archive_get_key, 0, 0)); +} + + +/* + Release the archive handler. + + SYNOPSIS + archive_db_end() + void + + RETURN + FALSE OK +*/ + +bool archive_db_end() +{ + hash_free(&archive_open_tables); + VOID(pthread_mutex_destroy(&archive_mutex)); + return FALSE; +} + + /* This method reads the header of a datafile and returns whether or not it was successful. */ @@ -269,23 +308,6 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) uint length; char *tmp_name; - if (!archive_init) - { - /* Hijack a mutex for init'ing the storage engine */ - pthread_mutex_lock(&LOCK_mysql_create_db); - if (!archive_init) - { - VOID(pthread_mutex_init(&archive_mutex,MY_MUTEX_INIT_FAST)); - if (hash_init(&archive_open_tables,system_charset_info,32,0,0, - (hash_get_key) archive_get_key,0,0)) - { - pthread_mutex_unlock(&LOCK_mysql_create_db); - return NULL; - } - archive_init++; - } - pthread_mutex_unlock(&LOCK_mysql_create_db); - } pthread_mutex_lock(&archive_mutex); length=(uint) strlen(table_name); @@ -371,6 +393,7 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE); if (gzclose(share->archive_write) == Z_ERRNO) rc= 1; + my_close(share->meta_file,MYF(0)); my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&archive_mutex); @@ -787,6 +810,7 @@ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt) goto error; } (void)write_meta_file(meta_file, rows_recorded, TRUE); + my_close(meta_file,MYF(0)); rc= 0; } diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 07bc7baa400..a511b5c67d6 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -105,3 +105,7 @@ public: THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); }; + +bool archive_db_init(void); +bool archive_db_end(void); + diff --git a/sql/field.cc b/sql/field.cc index 7d0e69681c0..aa2c5805bfe 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -524,6 +524,115 @@ Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table, return tmp; } +/* + SYNOPSIS + Field::quote_data() + unquoted_string Pointer pointing to the value of a field + + DESCRIPTION + Simple method that passes the field type to the method "type_quote" + To get a true/false value as to whether the value in string1 needs + to be enclosed with quotes. This ensures that values in the final + sql statement to be passed to the remote server will be quoted properly + + RETURN_VALUE + void Immediately - if string doesn't need quote + void Upon prepending/appending quotes on each side of variable + +*/ +bool Field::quote_data(String *unquoted_string) +{ + char escaped_string[IO_SIZE]; + char *unquoted_string_buffer= (char *)(unquoted_string->ptr()); + uint need_quotes; + + DBUG_ENTER("Field::quote_data"); + // this is the same call that mysql_real_escape_string() calls + escape_string_for_mysql(&my_charset_bin, (char *)escaped_string, + unquoted_string->ptr(), unquoted_string->length()); + + + if (is_null()) + DBUG_RETURN(0); + + need_quotes= needs_quotes(); + + if (need_quotes == 0) + { + DBUG_RETURN(0); + } + else + { + // reset string, then re-append with quotes and escaped values + unquoted_string->length(0); + if (unquoted_string->append("'")) + DBUG_RETURN(1); + if (unquoted_string->append((char *)escaped_string)) + DBUG_RETURN(1); + if (unquoted_string->append("'")) + DBUG_RETURN(1); + } + //DBUG_PRINT("Field::quote_data", + // ("FINAL quote_flag %d unquoted_string %s escaped_string %s", + //needs_quotes, unquoted_string->c_ptr_quick(), escaped_string)); + DBUG_RETURN(0); +} + +/* + Quote a field type if needed + + SYNOPSIS + Field::type_quote + + DESCRIPTION + Simple method to give true/false whether a field should be quoted. + Used when constructing INSERT and UPDATE queries to the remote server + see write_row and update_row + + RETURN VALUE + 0 if value is of type NOT needing quotes + 1 if value is of type needing quotes +*/ +bool Field::needs_quotes(void) +{ + DBUG_ENTER("Field::type_quote"); + + switch(type()) { + //FIX this when kernel is fixed + case MYSQL_TYPE_VARCHAR : + case FIELD_TYPE_STRING : + case FIELD_TYPE_VAR_STRING : + case FIELD_TYPE_YEAR : + case FIELD_TYPE_NEWDATE : + case FIELD_TYPE_TIME : + case FIELD_TYPE_TIMESTAMP : + case FIELD_TYPE_DATE : + case FIELD_TYPE_DATETIME : + case FIELD_TYPE_TINY_BLOB : + case FIELD_TYPE_BLOB : + case FIELD_TYPE_MEDIUM_BLOB : + case FIELD_TYPE_LONG_BLOB : + case FIELD_TYPE_GEOMETRY : + DBUG_RETURN(1); + + case FIELD_TYPE_DECIMAL : + case FIELD_TYPE_TINY : + case FIELD_TYPE_SHORT : + case FIELD_TYPE_INT24 : + case FIELD_TYPE_LONG : + case FIELD_TYPE_FLOAT : + case FIELD_TYPE_DOUBLE : + case FIELD_TYPE_LONGLONG : + case FIELD_TYPE_NULL : + case FIELD_TYPE_SET : + case FIELD_TYPE_ENUM : + DBUG_RETURN(0); + + default: DBUG_RETURN(0); + } + DBUG_RETURN(0); + +} /**************************************************************************** Field_null, a field that always return NULL diff --git a/sql/field.h b/sql/field.h index fd1ef09d14f..af300c8d471 100644 --- a/sql/field.h +++ b/sql/field.h @@ -228,6 +228,8 @@ public: ptr= old_ptr; return str; } + bool quote_data(String *unquoted_string); + bool needs_quotes(void); virtual bool send_binary(Protocol *protocol); virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) { @@ -1228,7 +1230,7 @@ public: int cmp(const char *a, const char *b) { return cmp_binary(a, b); } int key_cmp(const byte *a, const byte *b) - { return cmp_binary(a, b); } + { return cmp_binary((char *) a, (char *) b); } int key_cmp(const byte *str, uint length); int cmp_offset(uint row_offset); void get_key_image(char *buff, uint length, imagetype type); diff --git a/sql/filesort.cc b/sql/filesort.cc index 21f75fa5ea0..c4dbb82d8a5 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1184,7 +1184,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset) { sortorder->need_strxnfrm= 1; *multi_byte_charset= 1; - sortorder->length= sortorder->length*cs->strxfrm_multiply; + sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length); } } if (sortorder->field->maybe_null()) @@ -1197,7 +1197,7 @@ sortlength(SORT_FIELD *sortorder, uint s_length, bool *multi_byte_charset) sortorder->length=sortorder->item->max_length; if (use_strnxfrm((cs=sortorder->item->collation.collation))) { - sortorder->length= sortorder->length*cs->strxfrm_multiply; + sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length); sortorder->need_strxnfrm= 1; *multi_byte_charset= 1; } diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index ea8633febe6..5185e0bbe9a 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -123,8 +123,8 @@ ha_federated::write_row <for every field/column> - ha_federated::quote_data - ha_federated::quote_data + Field::quote_data + Field::quote_data </for every field/column> ha_federated::reset @@ -136,18 +136,18 @@ ha_federated::index_init ha_federated::index_read ha_federated::index_read_idx - ha_federated::quote_data + Field::quote_data ha_federated::rnd_next ha_federated::convert_row_to_internal_format ha_federated::update_row <quote 3 cols, new and old data> - <ha_federated::quote_data - <ha_federated::quote_data - <ha_federated::quote_data - <ha_federated::quote_data - <ha_federated::quote_data - <ha_federated::quote_data + Field::quote_data + Field::quote_data + Field::quote_data + Field::quote_data + Field::quote_data + Field::quote_data </quote 3 cols, new and old data> ha_federated::extra @@ -415,7 +415,7 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_fla share->scheme= my_strdup(table->s->comment, MYF(0)); - if (share->username= strstr(share->scheme, "://")) + if ((share->username= strstr(share->scheme, "://"))) { share->scheme[share->username - share->scheme] = '\0'; if (strcmp(share->scheme, "mysql") != 0) @@ -429,18 +429,18 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_fla } share->username+= 3; - if (share->hostname= strchr(share->username, '@')) + if ((share->hostname= strchr(share->username, '@'))) { share->username[share->hostname - share->username]= '\0'; share->hostname++; - if (share->password= strchr(share->username, ':')) + if ((share->password= strchr(share->username, ':'))) { share->username[share->password - share->username]= '\0'; share->password++; share->username= share->username; // make sure there isn't an extra / or @ - if (strchr(share->password, '/') || strchr(share->hostname, '@')) + if ((strchr(share->password, '/') || strchr(share->hostname, '@'))) { DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); @@ -453,14 +453,14 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table, uint table_create_fla user:@hostname:port/database/table Then password is a null string, so set to NULL */ - if (share->password[0] == '\0') + if ((share->password[0] == '\0')) share->password= NULL; } else share->username= share->username; // make sure there isn't an extra / or @ - if (strchr(share->username, '/') || strchr(share->hostname, '@')) + if ((strchr(share->username, '/')) || (strchr(share->hostname, '@'))) { DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); @@ -469,12 +469,12 @@ Then password is a null string, so set to NULL DBUG_RETURN(-1); } - if (share->database= strchr(share->hostname, '/')) + if ((share->database= strchr(share->hostname, '/'))) { share->hostname[share->database - share->hostname]= '\0'; share->database++; - if (share->sport= strchr(share->hostname, ':')) + if ((share->sport= strchr(share->hostname, ':'))) { share->hostname[share->sport - share->hostname]= '\0'; share->sport++; @@ -484,7 +484,7 @@ Then password is a null string, so set to NULL share->port= atoi(share->sport); } - if (share->table_base_name= strchr(share->database, '/')) + if ((share->table_base_name= strchr(share->database, '/'))) { share->database[share->table_base_name - share->database]= '\0'; share->table_base_name++; @@ -507,7 +507,7 @@ Then password is a null string, so set to NULL DBUG_RETURN(-1); } // make sure there's not an extra / - if (strchr(share->table_base_name, '/')) + if ((strchr(share->table_base_name, '/'))) { DBUG_PRINT("ha_federated::parse_url", ("this connection string is not in the correct format!!!\n")); @@ -586,126 +586,117 @@ uint ha_federated::convert_row_to_internal_format(byte *record, MYSQL_ROW row) DBUG_RETURN(0); } -/* - SYNOPSIS - quote_data() - unquoted_string Pointer pointing to the value of a field - field MySQL Field pointer to field being checked for type - - DESCRIPTION - Simple method that passes the field type to the method "type_quote" - To get a true/false value as to whether the value in string1 needs - to be enclosed with quotes. This ensures that values in the final - sql statement to be passed to the remote server will be quoted properly - - RETURN_VALUE - void Immediately - if string doesn't need quote - void Upon prepending/appending quotes on each side of variable - -*/ -void ha_federated::quote_data(String *unquoted_string, Field *field ) +bool ha_federated::create_where_from_key( + String *to, + KEY *key_info, + const byte *key, + uint key_length + ) { - char escaped_string[IO_SIZE]; - char *unquoted_string_buffer; - - unquoted_string_buffer= unquoted_string->c_ptr_quick(); - - int quote_flag; - DBUG_ENTER("ha_federated::quote_data"); - // this is the same call that mysql_real_escape_string() calls - escape_string_for_mysql(&my_charset_bin, (char *)escaped_string, - unquoted_string->c_ptr_quick(), unquoted_string->length()); - - DBUG_PRINT("ha_federated::quote_data", - ("escape_string_for_mysql unescaped %s escaped %s", - unquoted_string->c_ptr_quick(), escaped_string)); - - if (field->is_null()) - { - DBUG_PRINT("ha_federated::quote_data", - ("NULL, no quoted needed for unquoted_string %s, returning.", - unquoted_string->c_ptr_quick())); - DBUG_VOID_RETURN; - } + uint second_loop= 0; + KEY_PART_INFO *key_part; + bool needs_quotes; - quote_flag= type_quote(field->type()); - - if (quote_flag == 0) - { - DBUG_PRINT("ha_federated::quote_data", - ("quote flag 0 no quoted needed for unquoted_string %s, returning.", - unquoted_string->c_ptr_quick())); - DBUG_VOID_RETURN; - } - else + DBUG_ENTER("ha_federated::create_where_from_key"); + for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++) { - // reset string, then re-append with quotes and escaped values - unquoted_string->length(0); - unquoted_string->append("'"); - unquoted_string->append((char *)escaped_string); - unquoted_string->append("'"); - } - DBUG_PRINT("ha_federated::quote_data", - ("FINAL quote_flag %d unquoted_string %s escaped_string %s", - quote_flag, unquoted_string->c_ptr_quick(), escaped_string)); - DBUG_VOID_RETURN; -} - -/* - Quote a field type if needed + Field *field= key_part->field; + needs_quotes= field->needs_quotes(); + //bool needs_quotes= type_quote(field->type()); + DBUG_PRINT("ha_federated::create_where_from_key", ("key name %s type %d", field->field_name, field->type())); + uint length= key_part->length; + + if (second_loop++ && to->append(" AND ",5)) + DBUG_RETURN(1); + if (to->append('`') || to->append(field->field_name) || + to->append("` ",2)) + DBUG_RETURN(1); // Out of memory + + if (key_part->null_bit) + { + if (*key++) + { + if (to->append("IS NULL",7)) + DBUG_PRINT("ha_federated::create_where_from_key", ("NULL type %s", to->c_ptr_quick())); + DBUG_RETURN(1); + key_length-= key_part->store_length; + key+= key_part->store_length-1; + continue; + } + key_length--; + } + if (to->append("= ")) + DBUG_RETURN(1); + if (needs_quotes && to->append("'")) + DBUG_RETURN(1); + if (key_part->type == HA_KEYTYPE_BIT) + { + /* This is can be threated as a hex string */ + Field_bit *field= (Field_bit *) (key_part->field); + char buff[64+2], *ptr; + byte *end= (byte *)(key) + length; + + buff[0]='0'; + buff[1]='x'; + for (ptr= buff+2 ; key < end ; key++) + { + uint tmp= (uint) (uchar) *key; + *ptr++=_dig_vec_upper[tmp >> 4]; + *ptr++=_dig_vec_upper[tmp & 15]; + } + if (to->append(buff, (uint) (ptr-buff))) + DBUG_RETURN(1); - SYNOPSIS - ha_federated::type_quote - int field Enumerated field type number + DBUG_PRINT("ha_federated::create_where_from_key", ("bit type %s", to->c_ptr_quick())); + key_length-= length; + continue; + } + if (key_part->key_part_flag & HA_BLOB_PART) + { + uint blob_length= uint2korr(key); + key+= HA_KEY_BLOB_LENGTH; + key_length-= HA_KEY_BLOB_LENGTH; + if (append_escaped(to, (char *)(key), blob_length)) + DBUG_RETURN(1); + + DBUG_PRINT("ha_federated::create_where_from_key", ("blob type %s", to->c_ptr_quick())); + length= key_part->length; + } + else if (key_part->key_part_flag & HA_VAR_LENGTH_PART) + { + length= uint2korr(key); + key+= HA_KEY_BLOB_LENGTH; + if (append_escaped(to, (char *)(key), length)) + DBUG_RETURN(1); - DESCRIPTION - Simple method to give true/false whether a field should be quoted. - Used when constructing INSERT and UPDATE queries to the remote server - see write_row and update_row + DBUG_PRINT("ha_federated::create_where_from_key", ("varchar type %s", to->c_ptr_quick())); + } + else + { + DBUG_PRINT("ha_federated::create_where_from_key", ("else block, unknown type so far")); + char buff[MAX_FIELD_WIDTH]; + String str(buff, sizeof(buff), field->charset()), *res; - RETURN VALUE - 0 if value is of type NOT needing quotes - 1 if value is of type needing quotes -*/ -uint ha_federated::type_quote(int type) -{ - DBUG_ENTER("ha_federated::type_quote"); - DBUG_PRINT("ha_federated::type_quote", ("field type %d", type)); - - switch(type) { - //FIX this is a bug, fix when kernel is fixed - case MYSQL_TYPE_VARCHAR : - case FIELD_TYPE_STRING : - case FIELD_TYPE_VAR_STRING : - case FIELD_TYPE_YEAR : - case FIELD_TYPE_NEWDATE : - case FIELD_TYPE_TIME : - case FIELD_TYPE_TIMESTAMP : - case FIELD_TYPE_DATE : - case FIELD_TYPE_DATETIME : - case FIELD_TYPE_TINY_BLOB : - case FIELD_TYPE_BLOB : - case FIELD_TYPE_MEDIUM_BLOB : - case FIELD_TYPE_LONG_BLOB : - case FIELD_TYPE_GEOMETRY : - DBUG_RETURN(1); + res= field->val_str(&str, (char *)(key)); + if (field->result_type() == STRING_RESULT) + { + if (append_escaped(to, (char *) res->ptr(), res->length())) + DBUG_RETURN(1); + res= field->val_str(&str, (char *)(key)); - case FIELD_TYPE_DECIMAL : - case FIELD_TYPE_TINY : - case FIELD_TYPE_SHORT : - case FIELD_TYPE_INT24 : - case FIELD_TYPE_LONG : - case FIELD_TYPE_FLOAT : - case FIELD_TYPE_DOUBLE : - case FIELD_TYPE_LONGLONG : - case FIELD_TYPE_NULL : - case FIELD_TYPE_SET : - case FIELD_TYPE_ENUM : + DBUG_PRINT("ha_federated::create_where_from_key", ("else block, string type", to->c_ptr_quick())); + } + else if (to->append(res->ptr(), res->length())) + DBUG_RETURN(1); + } + if (needs_quotes && to->append("'")) + DBUG_RETURN(1); + DBUG_PRINT("ha_federated::create_where_from_key", ("final value for 'to' %s", to->c_ptr_quick())); + key+= length; + key_length-= length; DBUG_RETURN(0); - - default: DBUG_RETURN(0); } - DBUG_RETURN(0); + DBUG_RETURN(1); } int load_conn_info(FEDERATED_SHARE *share, TABLE *table) @@ -975,7 +966,7 @@ int ha_federated::write_row(byte * buf) int x= 0, num_fields= 0; Field **field; ulong current_query_id= 1; - ulong tmp_query_id; + ulong tmp_query_id= 1; int all_fields_have_same_query_id= 1; char insert_buffer[IO_SIZE]; @@ -1060,7 +1051,8 @@ int ha_federated::write_row(byte * buf) insert_string.append((*field)->field_name); // quote these fields if they require it - quote_data(&insert_field_value_string, *field); + + (*field)->quote_data(&insert_field_value_string); // append the value values_string.append(insert_field_value_string); insert_field_value_string.length(0); @@ -1068,9 +1060,10 @@ int ha_federated::write_row(byte * buf) // append commas between both fields and fieldnames insert_string.append(','); values_string.append(','); - DBUG_PRINT("ha_federated::write_row", - ("insert_string %s values_string %s insert_field_value_string %s", - insert_string.c_ptr_quick(), values_string.c_ptr_quick(), insert_field_value_string.c_ptr_quick())); + DBUG_PRINT("ha_federated::write_row", + ("insert_string %s values_string %s insert_field_value_string %s", + insert_string.c_ptr_quick(), values_string.c_ptr_quick(), + insert_field_value_string.c_ptr_quick())); } } @@ -1137,8 +1130,8 @@ int ha_federated::update_row( byte * new_data ) { - uint x= 0; - uint has_a_primary_key; + int x= 0; + uint has_a_primary_key= 0; int primary_key_field_num; char old_field_value_buffer[IO_SIZE], new_field_value_buffer[IO_SIZE]; char update_buffer[IO_SIZE], where_buffer[IO_SIZE]; @@ -1205,7 +1198,7 @@ int ha_federated::update_row( { // otherwise = (*field)->val_str(&new_field_value); - quote_data(&new_field_value, *field); + (*field)->quote_data(&new_field_value); if ( has_a_primary_key ) { @@ -1223,7 +1216,7 @@ int ha_federated::update_row( { (*field)->val_str(&old_field_value, (char *)(old_data + (*field)->offset())); - quote_data(&old_field_value, *field); + (*field)->quote_data(&old_field_value); where_string.append(old_field_value); } } @@ -1235,7 +1228,7 @@ int ha_federated::update_row( { (*field)->val_str(&old_field_value, (char *)(old_data + (*field)->offset())); - quote_data(&old_field_value, *field); + (*field)->quote_data(&old_field_value); where_string.append(old_field_value); } } @@ -1312,7 +1305,7 @@ int ha_federated::delete_row(const byte * buf) { delete_string.append("="); (*field)->val_str(&data_string); - quote_data(&data_string, *field); + (*field)->quote_data(&data_string); } delete_string.append(data_string); @@ -1366,8 +1359,11 @@ int ha_federated::index_read_idx(byte * buf, uint index, const byte * key, __attribute__((unused))) { char index_value[IO_SIZE]; + char key_value[IO_SIZE]; + char test_value[IO_SIZE]; String index_string(index_value, sizeof(index_value), &my_charset_bin); index_string.length(0); + uint keylen; char sql_query_buffer[IO_SIZE]; String sql_query(sql_query_buffer, sizeof(sql_query_buffer), &my_charset_bin); @@ -1376,20 +1372,20 @@ int ha_federated::index_read_idx(byte * buf, uint index, const byte * key, DBUG_ENTER("ha_federated::index_read_idx"); statistic_increment(table->in_use->status_var.ha_read_key_count,&LOCK_status); - index_string.length(0); - sql_query.length(0); - sql_query.append(share->select_query); sql_query.append(" WHERE "); - sql_query.append(table->key_info[index].key_part->field->field_name); - sql_query.append(" = "); - table->key_info[index].key_part->field->val_str(&index_string, (char *)(key)); - quote_data(&index_string, table->key_info[index].key_part->field); + keylen= strlen((char *)(key)); + create_where_from_key(&index_string, &table->key_info[index], key, keylen); sql_query.append(index_string); DBUG_PRINT("ha_federated::index_read_idx", - ("sql_query %s", sql_query.c_ptr_quick())); + ("current key %d key value %s index_string value %s length %d", index, (char *)(key),index_string.c_ptr_quick(), + index_string.length())); + + DBUG_PRINT("ha_federated::index_read_idx", + ("current position %d sql_query %s", current_position, + sql_query.c_ptr_quick())); if (mysql_real_query(mysql, sql_query.c_ptr_quick(), sql_query.length())) { @@ -1540,7 +1536,7 @@ int ha_federated::rnd_pos(byte * buf, byte *pos) { DBUG_ENTER("ha_federated::rnd_pos"); statistic_increment(table->in_use->status_var.ha_read_rnd_count,&LOCK_status); - memcpy(current_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos is not aligned + memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos is not aligned result->current_row= 0; result->data_cursor= current_position; DBUG_RETURN(rnd_next(buf)); diff --git a/sql/ha_federated.h b/sql/ha_federated.h index c11960a836f..56f5e6de4b7 100755 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -71,10 +71,8 @@ private: return 0 on success return errorcode otherwise */ - //FIX uint convert_row_to_internal_format(byte *buf, MYSQL_ROW row); - uint type_quote(int type); - void quote_data(String *string1, Field *field); + bool ha_federated::create_where_from_key(String *to, KEY *key_info, const byte *key, uint key_length); public: ha_federated(TABLE *table): handler(table), @@ -104,7 +102,7 @@ public: { return (HA_TABLE_SCAN_ON_INDEX | HA_NOT_EXACT_COUNT | HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED | HA_AUTO_PART_KEY | - HA_TABLE_SCAN_ON_INDEX); + HA_TABLE_SCAN_ON_INDEX | HA_CAN_INDEX_BLOBS); } /* This is a bitmap of flags that says how the storage engine @@ -132,7 +130,7 @@ public: /* The next method will never be called if you do not implement indexes. */ - virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; } + virtual double read_time(uint index, uint ranges, ha_rows rows) { return (double) rows / 20.0+1; } /* Everything below are methods that we implment in ha_federated.cc. diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 18ab6f42d28..01580586bf6 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -5787,11 +5787,12 @@ ha_innobase::store_lock( if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { /* If we are not doing a LOCK TABLE or DISCARD/IMPORT - TABLESPACE, then allow multiple writers */ + TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) && !thd->in_lock_tables - && !thd->tablespace_op) { + && !thd->tablespace_op + && thd->lex->sql_command != SQLCOM_TRUNCATE) { lock_type = TL_WRITE_ALLOW_WRITE; } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index badb486d16b..c12055a1d63 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -1055,6 +1055,42 @@ int ha_ndbcluster::get_metadata(const char *path) DBUG_RETURN(build_index_list(table, ILBP_OPEN)); } +static int fix_unique_index_attr_order(NDB_INDEX_DATA &data, + const NDBINDEX *index, + KEY *key_info) +{ + DBUG_ENTER("fix_unique_index_attr_order"); + unsigned sz= index->getNoOfIndexColumns(); + + if (data.unique_index_attrid_map) + my_free((char*)data.unique_index_attrid_map, MYF(0)); + data.unique_index_attrid_map= (unsigned char*)my_malloc(sz,MYF(MY_WME)); + + KEY_PART_INFO* key_part= key_info->key_part; + KEY_PART_INFO* end= key_part+key_info->key_parts; + DBUG_ASSERT(key_info->key_parts == sz); + for (unsigned i= 0; key_part != end; key_part++, i++) + { + const char *field_name= key_part->field->field_name; + unsigned name_sz= strlen(field_name); + if (name_sz >= NDB_MAX_ATTR_NAME_SIZE) + name_sz= NDB_MAX_ATTR_NAME_SIZE-1; +#ifndef DBUG_OFF + data.unique_index_attrid_map[i]= 255; +#endif + for (unsigned j= 0; j < sz; j++) + { + const NdbDictionary::Column *c= index->getColumn(j); + if (strncmp(field_name, c->getName(), name_sz) == 0) + { + data.unique_index_attrid_map[i]= j; + break; + } + } + DBUG_ASSERT(data.unique_index_attrid_map[i] != 255); + } + DBUG_RETURN(0); +} int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase) { @@ -1129,7 +1165,8 @@ int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase) const NDBINDEX *index= dict->getIndex(unique_index_name, m_tabname); if (!index) DBUG_RETURN(1); m_index[i].unique_index= (void *) index; - } + error= fix_unique_index_attr_order(m_index[i], index, key_info); + } } DBUG_RETURN(error); @@ -1187,6 +1224,11 @@ void ha_ndbcluster::release_metadata() { m_index[i].unique_index= NULL; m_index[i].index= NULL; + if (m_index[i].unique_index_attrid_map) + { + my_free((char *)m_index[i].unique_index_attrid_map, MYF(0)); + m_index[i].unique_index_attrid_map= NULL; + } } DBUG_VOID_RETURN; @@ -1355,7 +1397,7 @@ ha_ndbcluster::set_index_key(NdbOperation *op, const byte* ptr= key_part->null_bit ? key_ptr + 1 : key_ptr; char buf[256]; shrink_varchar(field, ptr, buf); - if (set_ndb_key(op, field, i, ptr)) + if (set_ndb_key(op, field, m_index[active_index].unique_index_attrid_map[i], ptr)) ERR_RETURN(m_active_trans->getNdbError()); key_ptr+= key_part->store_length; } @@ -1858,13 +1900,10 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op, // Set bound if not cancelled via type -1 if (p.bound_type != -1) { - char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE]; - strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name)); - truncated_field_name[sizeof(truncated_field_name)-1]= '\0'; const char* ptr= p.bound_ptr; char buf[256]; shrink_varchar(field, ptr, buf); - if (op->setBound(truncated_field_name, p.bound_type, ptr)) + if (op->setBound(i, p.bound_type, ptr)) ERR_RETURN(op->getNdbError()); } } @@ -3634,14 +3673,14 @@ static int create_ndb_column(NDBCOL &col, col.setLength(1); break; // Date types - case MYSQL_TYPE_TIMESTAMP: - col.setType(NDBCOL::Unsigned); - col.setLength(1); - break; case MYSQL_TYPE_DATETIME: col.setType(NDBCOL::Datetime); col.setLength(1); break; + case MYSQL_TYPE_DATE: // ? + col.setType(NDBCOL::Char); + col.setLength(field->pack_length()); + break; case MYSQL_TYPE_NEWDATE: col.setType(NDBCOL::Date); col.setLength(1); @@ -3650,10 +3689,13 @@ static int create_ndb_column(NDBCOL &col, col.setType(NDBCOL::Time); col.setLength(1); break; - case MYSQL_TYPE_DATE: // ? - case MYSQL_TYPE_YEAR: - col.setType(NDBCOL::Char); - col.setLength(field->pack_length()); + case MYSQL_TYPE_YEAR: + col.setType(NDBCOL::Year); + col.setLength(1); + break; + case MYSQL_TYPE_TIMESTAMP: + col.setType(NDBCOL::Timestamp); + col.setLength(1); break; // Char types case MYSQL_TYPE_STRING: @@ -4192,9 +4234,10 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg): for (i= 0; i < MAX_KEY; i++) { - m_index[i].type= UNDEFINED_INDEX; - m_index[i].unique_index= NULL; - m_index[i].index= NULL; + m_index[i].type= UNDEFINED_INDEX; + m_index[i].unique_index= NULL; + m_index[i].index= NULL; + m_index[i].unique_index_attrid_map= NULL; } DBUG_VOID_RETURN; diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h index 52b7a0ac915..c660d8f618d 100644 --- a/sql/ha_ndbcluster.h +++ b/sql/ha_ndbcluster.h @@ -52,6 +52,7 @@ typedef struct ndb_index_data { NDB_INDEX_TYPE type; void *index; void *unique_index; + unsigned char *unique_index_attrid_map; } NDB_INDEX_DATA; typedef struct st_ndbcluster_share { diff --git a/sql/handler.cc b/sql/handler.cc index b1b741dfee9..059d1feaed1 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -373,6 +373,16 @@ int ha_init() opt_using_transactions=1; } #endif +#ifdef HAVE_ARCHIVE_DB + if (have_archive_db == SHOW_OPTION_YES) + { + if (archive_db_init()) + { + have_archive_db= SHOW_OPTION_DISABLED; + error= 1; + } + } +#endif return error; } @@ -404,6 +414,10 @@ int ha_panic(enum ha_panic_function flag) if (have_ndbcluster == SHOW_OPTION_YES) error|=ndbcluster_end(); #endif +#ifdef HAVE_ARCHIVE_DB + if (have_archive_db == SHOW_OPTION_YES) + error|= archive_db_end(); +#endif if (ha_finish_errors()) error= 1; return error; diff --git a/sql/item_create.cc b/sql/item_create.cc index 8a5aeb6c9b7..9fb44658dd5 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -370,13 +370,14 @@ Item *create_func_space(Item *a) { uint dummy_errors; sp= new Item_string("",0,cs); - sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); + if (sp) + sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors); } else { sp= new Item_string(" ",1,cs); } - return new Item_func_repeat(sp, a); + return sp ? new Item_func_repeat(sp, a) : 0; } Item *create_func_soundex(Item* a) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index be89aa3f86d..29837c3afbd 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1234,7 +1234,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2) { Field* f = *field; int len = *lengths++; - int res = f->cmp(key1, key2); + int res = f->cmp((char *) key1, (char *) key2); if (res) return res; key1 += len; @@ -1688,7 +1688,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1, { int res; uint offset= (uint) (field->ptr - record); - if ((res= field->cmp(key1 + offset, key2 + offset))) + if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) return res; } } @@ -1722,7 +1722,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2) { int res; uint offset= (uint) (field->ptr - record); - if ((res= field->cmp(key1 + offset, key2 + offset))) + if ((res= field->cmp((char *) key1 + offset, (char *) key2 + offset))) return (*order_item)->asc ? res : -res; } } diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 32813454fef..5a069aee554 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2134,7 +2134,6 @@ String *Item_char_typecast::val_str(String *str) String *res; uint32 length; -#if 0 if (!charset_conversion) { if (!(res= args[0]->val_str(str))) @@ -2144,7 +2143,6 @@ String *Item_char_typecast::val_str(String *str) } } else -#endif { // Convert character set if differ uint dummy_errors; @@ -2182,9 +2180,18 @@ String *Item_char_typecast::val_str(String *str) void Item_char_typecast::fix_length_and_dec() { uint32 char_length; - charset_conversion= !my_charset_same(args[0]->collation.collation, cast_cs) && - args[0]->collation.collation != &my_charset_bin && - cast_cs != &my_charset_bin; + /* + We always force character set conversion if cast_cs + is a multi-byte character set. It garantees that the + result of CAST is a well-formed string. + For single-byte character sets we allow just to copy + from the argument. A single-byte character sets string + is always well-formed. + */ + charset_conversion= (cast_cs->mbmaxlen > 1) || + !my_charset_same(args[0]->collation.collation, cast_cs) && + args[0]->collation.collation != &my_charset_bin && + cast_cs != &my_charset_bin; collation.set(cast_cs, DERIVATION_IMPLICIT); char_length= (cast_length >= 0) ? cast_length : args[0]->max_length/args[0]->collation.collation->mbmaxlen; diff --git a/sql/key.cc b/sql/key.cc index aec294e370a..c5ed60b129c 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -135,7 +135,7 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) { key_length-= HA_KEY_BLOB_LENGTH; length= min(key_length, key_part->length); - key_part->field->get_key_image(to_key, length, Field::itRAW); + key_part->field->get_key_image((char *) to_key, length, Field::itRAW); to_key+= HA_KEY_BLOB_LENGTH; } else @@ -217,7 +217,7 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info, { key_length-= HA_KEY_BLOB_LENGTH; length= min(key_length, key_part->length); - key_part->field->set_key_image(from_key, length); + key_part->field->set_key_image((char *) from_key, length); from_key+= HA_KEY_BLOB_LENGTH; } else diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 5a222a1ce10..bd0e1455eb2 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -712,6 +712,10 @@ void free_des_key_file(); /* sql_do.cc */ bool mysql_do(THD *thd, List<Item> &values); +/* sql_analyse.h */ +bool append_escaped(String *to_str, String *from_str); +bool append_escaped(String *to_str, char *from, uint from_len); + /* sql_show.cc */ bool mysqld_show_open_tables(THD *thd,const char *wild); bool mysqld_show_logs(THD *thd); @@ -978,7 +982,7 @@ extern Gt_creator gt_creator; extern Lt_creator lt_creator; extern Ge_creator ge_creator; extern Le_creator le_creator; -extern char language[LIBLEN],reg_ext[FN_EXTLEN]; +extern char language[FN_REFLEN], reg_ext[FN_EXTLEN]; extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN]; extern char pidfile_name[FN_REFLEN], system_time_zone[30], *opt_init_file; extern char log_error_file[FN_REFLEN]; @@ -1001,8 +1005,7 @@ extern ulong ha_read_count, ha_discover_count; extern ulong table_cache_size; extern ulong max_connections,max_connect_errors, connect_timeout; extern ulong slave_net_timeout; -extern ulong max_user_connections; -extern my_bool timed_mutexes; +extern uint max_user_connections; extern ulong what_to_log,flush_time; extern ulong query_buff_size, thread_stack,thread_stack_min; extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index db18c275a4d..ae27af1e755 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -333,9 +333,9 @@ ulong delayed_insert_errors,flush_time, thread_created; ulong specialflag=0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong max_connections,max_used_connections, - max_connect_errors, max_user_connections = 0; + max_connect_errors; +uint max_user_connections= 0; ulong thread_id=1L,current_pid; -my_bool timed_mutexes= 0; ulong slow_launch_threads = 0, sync_binlog_period; ulong expire_logs_days = 0; ulong rpl_recovery_rank=0; @@ -351,7 +351,7 @@ char *default_tz_name; char log_error_file[FN_REFLEN], glob_hostname[FN_REFLEN]; char* log_error_file_ptr= log_error_file; char mysql_real_data_home[FN_REFLEN], - language[LIBLEN],reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], + language[FN_REFLEN], reg_ext[FN_EXTLEN], mysql_charsets_dir[FN_REFLEN], *mysqld_user,*mysqld_chroot, *opt_init_file, *opt_init_connect, *opt_init_slave, def_ft_boolean_syntax[sizeof(ft_boolean_syntax)]; @@ -3036,12 +3036,11 @@ You should consider changing lower_case_table_names to 1 or 2", (test_if_case_insensitive(mysql_real_data_home) == 1))) { if (global_system_variables.log_warnings) - sql_print_warning("\ -You have forced lower_case_table_names to 2 through a command-line \ -option, even though your file system '%s' is case sensitive. This means \ -that you can create a table that you can then no longer access. \ -You should consider changing lower_case_table_names to 0.", + sql_print_warning("lower_case_table_names was set to 2, even though your " + "the file system '%s' is case sensitive. Now setting " + "lower_case_table_names to 0 to avoid future problems.", mysql_real_data_home); + lower_case_table_names= 0; } select_thread=pthread_self(); @@ -5262,8 +5261,8 @@ The minimum value for this variable is 4096.", REQUIRED_ARG, 32, 1, ~0L, 0, 1, 0}, {"max_user_connections", OPT_MAX_USER_CONNECTIONS, "The maximum number of active connections for a single user (0 = no limit).", - (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_ULONG, - REQUIRED_ARG, 0, 1, ~0L, 0, 1, 0}, + (gptr*) &max_user_connections, (gptr*) &max_user_connections, 0, GET_UINT, + REQUIRED_ARG, 0, 1, ~0, 0, 1, 0}, {"max_write_lock_count", OPT_MAX_WRITE_LOCK_COUNT, "After this many write locks, allow some read locks to run in between.", (gptr*) &max_write_lock_count, (gptr*) &max_write_lock_count, 0, GET_ULONG, diff --git a/sql/opt_range.cc b/sql/opt_range.cc index c3b84564504..e5799bfd509 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1891,7 +1891,7 @@ double get_sweep_read_cost(const PARAM *param, ha_rows records) else { double n_blocks= - ceil((double)param->table->file->data_file_length / IO_SIZE); + ceil(ulonglong2double(param->table->file->data_file_length) / IO_SIZE); double busy_blocks= n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(records))); if (busy_blocks < 1.0) diff --git a/sql/set_var.cc b/sql/set_var.cc index 552d2692c3c..d09de8550f0 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -28,7 +28,7 @@ - If the variable is thread specific, add it to 'system_variables' struct. If not, add it to mysqld.cc and an declaration in 'mysql_priv.h' - If the variable should be changed from the command line, add a definition - of it in the my_option structure list in mysqld.dcc + of it in the my_option structure list in mysqld.cc - Don't forget to initialize new fields in global_system_variables and max_system_variables! - If the variable should show up in 'show variables' add it to the @@ -587,6 +587,7 @@ sys_var *sys_variables[]= &sys_max_tmp_tables, &sys_max_user_connections, &sys_max_write_lock_count, + &sys_multi_range_count, &sys_myisam_data_pointer_size, &sys_myisam_max_extra_sort_file_size, &sys_myisam_max_sort_file_size, @@ -736,7 +737,7 @@ struct show_var_st init_vars[]= { {"have_crypt", (char*) &have_crypt, SHOW_HAVE}, {"have_csv", (char*) &have_csv_db, SHOW_HAVE}, {"have_example_engine", (char*) &have_example_db, SHOW_HAVE}, - {"have_federated_db", (char*) &have_federated_db, SHOW_HAVE}, + {"have_federated_engine", (char*) &have_federated_db, SHOW_HAVE}, {"have_geometry", (char*) &have_geometry, SHOW_HAVE}, {"have_innodb", (char*) &have_innodb, SHOW_HAVE}, {"have_isam", (char*) &have_isam, SHOW_HAVE}, @@ -832,6 +833,7 @@ struct show_var_st init_vars[]= { {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, + {sys_multi_range_count.name, (char*) &sys_multi_range_count, SHOW_SYS}, {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS}, {sys_myisam_max_extra_sort_file_size.name, (char*) &sys_myisam_max_extra_sort_file_size, @@ -1605,6 +1607,14 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base) var_type= OPT_GLOBAL; } switch (type()) { + case SHOW_INT: + { + uint value; + pthread_mutex_lock(&LOCK_global_system_variables); + value= *(uint*) value_ptr(thd, var_type, base); + pthread_mutex_unlock(&LOCK_global_system_variables); + return new Item_uint((int32) value); + } case SHOW_LONG: { ulong value; diff --git a/sql/set_var.h b/sql/set_var.h index 7c9f11041c8..0f30f764ed5 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -740,7 +740,7 @@ public: return type != OPT_GLOBAL || !option_limits; } void set_default(THD *thd, enum_var_type type); - SHOW_TYPE type() { return SHOW_LONG; } + SHOW_TYPE type() { return SHOW_INT; } byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am index cfbbb36c489..608bbdb7ae6 100644 --- a/sql/share/Makefile.am +++ b/sql/share/Makefile.am @@ -14,10 +14,11 @@ dist-hook: all: english/errmsg.sys # Use the english errmsg.sys as a flag that all errmsg.sys needs to be -# created. Normally these are created by extra/Makefile.am +# created. Normally these are created by extra/Makefile english/errmsg.sys: errmsg.txt - $(top_builddir)/extra/comp_err --charset=$(srcdir)/charsets --out-dir=$(top_builddir)/sql/share/ --header_file=$(top_builddir)/extra/mysqld_error.h --state_file=$(top_builddir)/extra/sql_state.h --in_file=errmsg.txt + rm $(top_builddir)/include/mysqld_error.h + (cd $(top_builddir)/extra && $(MAKE)) install-data-local: for lang in @AVAILABLE_LANGUAGES@; \ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f9d95b2cde5..71d042eda02 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1494,12 +1494,12 @@ static bool update_user_table(THD *thd, const char *host, const char *user, DBUG_RETURN(1); /* purecov: deadcode */ table->field[0]->store(host,(uint) strlen(host), system_charset_info); table->field[1]->store(user,(uint) strlen(user), system_charset_info); - key_copy(user_key, table->record[0], table->key_info, + key_copy((byte *) user_key, table->record[0], table->key_info, table->key_info->key_length); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0], 0, - user_key, table->key_info->key_length, + (byte *) user_key, table->key_info->key_length, HA_READ_KEY_EXACT)) { my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index ce58c585061..3f97cab1511 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -59,7 +59,8 @@ int compare_ulonglong2(void* cmp_arg __attribute__((unused)), return compare_ulonglong(s,t); } -static bool append_escaped(String *to_str, String *from_str); +bool append_escaped(String *to_str, String *from_str); +bool append_escaped(String *to_str, char *from, uint from_len); Procedure * proc_analyse_init(THD *thd, ORDER *param, select_result *result, @@ -1052,7 +1053,7 @@ uint check_ulonglong(const char *str, uint length) 1 Out of memory */ -static bool append_escaped(String *to_str, String *from_str) +bool append_escaped(String *to_str, String *from_str) { char *from, *end, c; @@ -1086,3 +1087,38 @@ static bool append_escaped(String *to_str, String *from_str) } return 0; } + +bool append_escaped(String *to_str, char *from, uint from_len) +{ + char *end, c; + + if (to_str->realloc(to_str->length() + from_len)) + return 1; + + end= from + from_len; + + for (; from < end; from++) + { + c= *from; + switch (c) { + case '\0': + c= '0'; + break; + case '\032': + c= 'Z'; + break; + case '\\': + case '\'': + break; + default: + goto normal_character; + } + if (to_str->append('\\')) + return 1; + + normal_character: + if (to_str->append(c)) + return 1; + } + return 0; +} diff --git a/sql/sql_class.h b/sql/sql_class.h index f635aa62000..240208584e7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1281,6 +1281,7 @@ public: unit= u; return 0; } + virtual int prepare2(void) { return 0; } /* Because of peculiarities of prepared statements protocol we need to know number of columns in the result set (if @@ -1380,6 +1381,7 @@ class select_insert :public select_result_interceptor { enum_duplicates duplic, bool ignore); ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); + int prepare2(void); bool send_data(List<Item> &items); virtual void store_values(List<Item> &values); void send_error(uint errcode,const char *err); diff --git a/sql/sql_help.cc b/sql/sql_help.cc index 7bf28a439b6..759b535da53 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -558,8 +558,13 @@ SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, TABLE_LIST *tables, { if (!cond->fixed) cond->fix_fields(thd, tables, &cond); // can never fail + + /* Assume that no indexes cover all required fields */ + table->used_keys.clear_all(); + SQL_SELECT *res= make_select(table,0,0,cond,error); - if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR))) + if (*error || (res && res->check_quick(thd, 0, HA_POS_ERROR)) || + (res->quick && res->quick->reset())) { delete res; res=0; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ceb31f76953..4cb62d5e9d7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1802,13 +1802,22 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) thd->lex->current_select->options|= OPTION_BUFFER_RESULT; thd->lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } - + else + { + /* + We must not yet prepare the result table if it is the same as one of the + source tables (INSERT SELECT). The preparation may disable + indexes on the result table, which may be used during the select, if it + is the same table (Bug #6034). Do the preparation after the select phase + in select_insert::prepare2(). + */ + if (info.ignore || info.handle_duplicates != DUP_ERROR) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + table->file->start_bulk_insert((ha_rows) 0); + } restore_record(table,s->default_values); // Get empty record table->next_number_field=table->found_next_number_field; thd->cuted_fields=0; - if (info.ignore || info.handle_duplicates != DUP_ERROR) - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - table->file->start_bulk_insert((ha_rows) 0); thd->no_trans_update= 0; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & @@ -1819,6 +1828,36 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } +/* + Finish the preparation of the result table. + + SYNOPSIS + select_insert::prepare2() + void + + DESCRIPTION + If the result table is the same as one of the source tables (INSERT SELECT), + the result table is not finally prepared at the join prepair phase. + Do the final preparation now. + + RETURN + 0 OK +*/ + +int select_insert::prepare2(void) +{ + DBUG_ENTER("select_insert::prepare2"); + + if (thd->lex->current_select->options & OPTION_BUFFER_RESULT) + { + if (info.ignore || info.handle_duplicates != DUP_ERROR) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + table->file->start_bulk_insert((ha_rows) 0); + } + return 0; +} + + void select_insert::cleanup() { /* select_insert/select_create are never re-used in prepared statement */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c0bcaf771a5..7205baae59e 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5339,6 +5339,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, ptr->table_name, information_schema_name.str); DBUG_RETURN(0); } + ptr->schema_table_name= ptr->table_name; ptr->schema_table= schema_table; } ptr->select_lex= lex->current_select; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index acb7d8f48f1..60273d21d9f 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1164,6 +1164,7 @@ JOIN::exec() DBUG_VOID_RETURN; } } + (void) result->prepare2(); // Currently, this cannot fail. if (!tables_list) { // Only test of functions @@ -4473,16 +4474,9 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, x = used key parts (1 <= x <= c) */ double rec_per_key; -#if 0 - if (!(rec_per_key=(double) - keyinfo->rec_per_key[keyinfo->key_parts-1])) - rec_per_key=(double) s->records/rec+1; -#else rec_per_key= keyinfo->rec_per_key[keyinfo->key_parts-1] ? (double) keyinfo->rec_per_key[keyinfo->key_parts-1] : (double) s->records/rec+1; -#endif - if (!s->records) tmp=0; else if (rec_per_key/(double) s->records >= 0.01) @@ -13159,7 +13153,8 @@ bool JOIN::change_result(select_result *res) { DBUG_ENTER("JOIN::change_result"); result= res; - if (!procedure && result->prepare(fields_list, select_lex->master_unit())) + if (!procedure && (result->prepare(fields_list, select_lex->master_unit()) || + result->prepare2())) { DBUG_RETURN(TRUE); } diff --git a/sql/sql_show.cc b/sql/sql_show.cc index b909e9cec1b..e9126871045 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1802,7 +1802,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) res= open_and_lock_tables(thd, show_table_list); if (schema_table->process_table(thd, show_table_list, table, res, show_table_list->db, - show_table_list->table_name)) + show_table_list->alias)) { DBUG_RETURN(1); } @@ -1911,7 +1911,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) show_table_list->lock_type= lock_type; res= open_and_lock_tables(thd, show_table_list); if (schema_table->process_table(thd, show_table_list, table, - res, base_name, file_name)) + res, base_name, + show_table_list->alias)) { DBUG_RETURN(1); } @@ -3183,8 +3184,17 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list) } table->s->tmp_table= TMP_TABLE; table->grant.privilege= SELECT_ACL; - table->alias_name_used= 0; - table_list->schema_table_name= table_list->table_name; + /* + This test is necessary to make + case insensitive file systems + + upper case table names(information schema tables) + + views + working correctly + */ + if (table_list->schema_table_name) + table->alias_name_used= my_strcasecmp(table_alias_charset, + table_list->schema_table_name, + table_list->alias); table_list->table_name= (char*) table->s->table_name; table_list->table= table; table->next= thd->derived_tables; diff --git a/sql/table.cc b/sql/table.cc index 82ad32341c0..69a132329c0 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -305,7 +305,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, if (!(record= (char *) alloc_root(&outparam->mem_root, rec_buff_length * records))) goto err; /* purecov: inspected */ - share->default_values= record; + share->default_values= (byte *) record; if (my_pread(file,(byte*) record, (uint) share->reclength, (ulong) (uint2korr(head+6)+ ((uint2korr(head+14) == 0xffff ? @@ -320,9 +320,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat, } else { - outparam->record[0]= record+ rec_buff_length; + outparam->record[0]= (byte *) record+ rec_buff_length; if (records > 2) - outparam->record[1]= record+ rec_buff_length*2; + outparam->record[1]= (byte *) record+ rec_buff_length*2; else outparam->record[1]= outparam->record[0]; // Safety } |