diff --git a/Docs/manual.texi b/Docs/manual.texi index 4232065c9fd..0213446f044 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -14374,12 +14374,16 @@ like an integer (64-bit precision). In string context these act like a binary string where each pair of hex digits is converted to a character: @example +mysql> SELECT x'FF' + -> 255 mysql> SELECT 0xa+0; -> 10 mysql> select 0x5061756c; -> Paul @end example +The x'hexstring' syntax (new in 4.0) is based on ANSI SQL and the 0x +syntax is based on ODBC. Hexadecimal strings are often used by ODBC to give values for BLOB columns. @tindex NULL value @@ -46436,11 +46440,13 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}. @itemize @bullet @item +Allow ANSI SQL syntax @code{X'hexadecimal-number'} +@item Tree-like cache to speed up bulk inserts and @code{myisam_bulk_insert_tree_size} variable. @item Added @code{ALTER TABLE table_name DISABLE KEYS} and - @code{ALTER TABLE table_name ENABLE KEYS} commands. +@code{ALTER TABLE table_name ENABLE KEYS} commands. @item @code{LOAD DATA FROM MASTER} "auto-magically" sets up a slave. @item diff --git a/client/mysqldump.c b/client/mysqldump.c index 4893c13a0a0..5aa9addfe76 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -37,7 +37,7 @@ ** Tõnu Samuel **/ -#define DUMP_VERSION "8.14" +#define DUMP_VERSION "8.15" #include #include @@ -274,12 +274,12 @@ puts("\ static void write_heder(FILE *sql_file, char *db_name) { - fprintf(sql_file, "# MySQL dump %s\n#\n", DUMP_VERSION); - fprintf(sql_file, "# Host: %s Database: %s\n", + fprintf(sql_file, "-- MySQL dump %s\n#\n", DUMP_VERSION); + fprintf(sql_file, "-- Host: %s Database: %s\n", current_host ? current_host : "localhost", db_name ? db_name : ""); - fputs("#--------------------------------------------------------\n", + fputs("---------------------------------------------------------\n", sql_file); - fprintf(sql_file, "# Server version\t%s\n", + fprintf(sql_file, "-- Server version\t%s\n", mysql_get_server_info(&mysql_connection)); return; } /* write_heder */ @@ -515,7 +515,7 @@ static int dbConnect(char *host, char *user,char *passwd) DBUG_ENTER("dbConnect"); if (verbose) { - fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost"); + fprintf(stderr, "-- Connecting to %s...\n", host ? host : "localhost"); } mysql_init(&mysql_connection); if (opt_compress) @@ -542,7 +542,7 @@ static int dbConnect(char *host, char *user,char *passwd) static void dbDisconnect(char *host) { if (verbose) - fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost"); + fprintf(stderr, "-- Disconnecting from %s...\n", host ? host : "localhost"); mysql_close(sock); } /* dbDisconnect */ @@ -608,7 +608,7 @@ static uint getTableStructure(char *table, char* db) delayed= opt_delayed ? " DELAYED " : ""; if (verbose) - fprintf(stderr, "# Retrieving table structure for table %s...\n", table); + fprintf(stderr, "-- Retrieving table structure for table %s...\n", table); sprintf(insert_pat,"SET OPTION SQL_QUOTE_SHOW_CREATE=%d", opt_quoted); table_name=quote_name(table,table_buff); @@ -837,7 +837,7 @@ static uint getTableStructure(char *table, char* db) { /* If old MySQL version */ if (verbose) fprintf(stderr, - "# Warning: Couldn't get status information for table '%s' (%s)\n", + "-- Warning: Couldn't get status information for table '%s' (%s)\n", table,mysql_error(sock)); } } @@ -934,7 +934,7 @@ static void dumpTable(uint numFields, char *table) ulong rownr, row_break, total_length, init_length; if (verbose) - fprintf(stderr, "# Sending SELECT query...\n"); + fprintf(stderr, "-- Sending SELECT query...\n"); if (path) { char filename[FN_REFLEN], tmp_path[FN_REFLEN]; @@ -977,10 +977,10 @@ static void dumpTable(uint numFields, char *table) sprintf(query, "SELECT * FROM %s", quote_name(table,table_buff)); if (where) { - fprintf(result_file,"# WHERE: %s\n",where); + fprintf(result_file,"-- WHERE: %s\n",where); strxmov(strend(query), " WHERE ",where,NullS); } - fputs("#\n\n", result_file); + fputs("\n\n", result_file); if (mysql_query(sock, query)) { @@ -997,7 +997,7 @@ static void dumpTable(uint numFields, char *table) return; } if (verbose) - fprintf(stderr, "# Retrieving rows...\n"); + fprintf(stderr, "-- Retrieving rows...\n"); if (mysql_num_fields(res) != numFields) { fprintf(stderr,"%s: Error in field count for table: '%s' ! Aborting.\n", diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d6f5b7c523f..fc39b73ab23 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -322,17 +322,9 @@ net_safe_read(MYSQL *mysql) if (len > 3) { char *pos=(char*) net->read_pos+1; - if (mysql->protocol_version > 9) - { /* New client protocol */ - net->last_errno=uint2korr(pos); - pos+=2; - len-=2; - } - else - { - net->last_errno=CR_UNKNOWN_ERROR; - len--; - } + net->last_errno=uint2korr(pos); + pos+=2; + len-=2; (void) strmake(net->last_error,(char*) pos, min(len,sizeof(net->last_error)-1)); } @@ -1404,6 +1396,7 @@ mysql_ssl_clear(MYSQL *mysql) ** If host == 0 then use localhost **************************************************************************/ +#ifdef USE_OLD_FUNCTIONS MYSQL * STDCALL mysql_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd) @@ -1420,6 +1413,7 @@ mysql_connect(MYSQL *mysql,const char *host, DBUG_RETURN(res); } } +#endif /* @@ -1651,8 +1645,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, DBUG_DUMP("packet",(char*) net->read_pos,10); DBUG_PRINT("info",("mysql protocol version %d, server=%d", PROTOCOL_VERSION, mysql->protocol_version)); - if (mysql->protocol_version != PROTOCOL_VERSION && - mysql->protocol_version != PROTOCOL_VERSION-1) + if (mysql->protocol_version != PROTOCOL_VERSION) { net->last_errno= CR_VERSION_ERROR; sprintf(net->last_error, ER(CR_VERSION_ERROR), mysql->protocol_version, @@ -2547,6 +2540,7 @@ mysql_list_processes(MYSQL *mysql) } +#ifdef USE_OLD_FUNCTIONS int STDCALL mysql_create_db(MYSQL *mysql, const char *db) { @@ -2563,6 +2557,7 @@ mysql_drop_db(MYSQL *mysql, const char *db) DBUG_PRINT("enter",("db: %s",db)); DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(uint) strlen(db),0)); } +#endif int STDCALL diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c index e5ea58148e3..5b1d4b0ed61 100644 --- a/myisam/myisamchk.c +++ b/myisam/myisamchk.c @@ -258,8 +258,6 @@ static void usage(void) -k, --keys-used=# Tell MyISAM to update only some specific keys. # is a\n\ bit mask of which keys to use. This can be used to\n\ get faster inserts!\n\ - -l, --no-symlinks Do not follow symbolic links. Normally\n\ - myisamchk repairs the table a symlink points at.\n\ -r, --recover Can fix almost anything except unique keys that aren't\n\ unique.\n\ -n, --sort-recover Force recovering with sorting even if the temporary\n\ diff --git a/mysql-test/r/varbinary.result b/mysql-test/r/varbinary.result index 62aeae21970..bb4aaefe057 100644 --- a/mysql-test/r/varbinary.result +++ b/mysql-test/r/varbinary.result @@ -2,5 +2,9 @@ A 65 9223372036854775807 -1 0x31+1 concat(0x31)+1 -0xf 50 2 -15 +x'31' X'ffff'+0 +1 65535 table type possible_keys key key_len ref rows Extra t1 const UNIQ UNIQ 8 const 1 +x xx +1 2 diff --git a/mysql-test/t/varbinary.test b/mysql-test/t/varbinary.test index 0ab26f51e65..7b0050fb2eb 100644 --- a/mysql-test/t/varbinary.test +++ b/mysql-test/t/varbinary.test @@ -4,6 +4,7 @@ select 0x41,0x41+0,0x41 | 0x7fffffffffffffff | 0,0xffffffffffffffff | 0 ; select 0x31+1,concat(0x31)+1,-0xf; +select x'31',X'ffff'+0; # # Test of hex constants in WHERE: @@ -14,3 +15,18 @@ insert into t1 set UNIQ=0x38afba1d73e6a18a; insert into t1 set UNIQ=123; explain select * from t1 where UNIQ=0x38afba1d73e6a18a; drop table t1; + +# +# Test error conditions +# +--error 1064 +select x'hello'; +--error 1064 +select 0xfg; + +# +# Test likely error conditions +# +create table t1 select 1 as x, 2 as xx; +select x,xx from t1; +drop table t1; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 3f6c09073e6..8f77931a05f 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -430,7 +430,7 @@ int yylex(void *arg) switch(state) { case STATE_OPERATOR_OR_IDENT: // Next is operator or keyword case STATE_START: // Start of token - // Skipp startspace + // Skip startspace for (c=yyGet() ; (state_map[c] == STATE_SKIP) ; c= yyGet()) { if (c == '\n') @@ -458,6 +458,11 @@ int yylex(void *arg) return((int) c); case STATE_IDENT: // Incomplete keyword or ident + if ((c == 'x' || c == 'X') && yyPeek() == '\'') + { // Found x'hex-number' + state=STATE_HEX_NUMBER; + break; + } #if defined(USE_MB) && defined(USE_MB_IDENT) if (use_mb(default_charset_info)) { @@ -520,7 +525,7 @@ int yylex(void *arg) c=yyGet(); // should be '.' return((int) c); - case STATE_NUMBER_IDENT: // number or ident which starts with num + case STATE_NUMBER_IDENT: // number or ident which num-start while (isdigit((c = yyGet()))) ; if (state_map[c] != STATE_IDENT) { // Can't be identifier @@ -546,10 +551,10 @@ int yylex(void *arg) lex->tok_start[0] == '0' ) { // Varbinary while (isxdigit((c = yyGet()))) ; - if ((lex->ptr - lex->tok_start) >= 4) + if ((lex->ptr - lex->tok_start) >= 4 && state_map[c] != STATE_IDENT) { yylval->lex_str=get_token(lex,yyLength()); - yylval->lex_str.str+=2; // Skipp 0x + yylval->lex_str.str+=2; // Skip 0x yylval->lex_str.length-=2; lex->yytoklen-=2; return (HEX_NUM); @@ -604,20 +609,21 @@ int yylex(void *arg) return(IDENT); case STATE_USER_VARIABLE_DELIMITER: - lex->tok_start=lex->ptr; // Skipp first ` + lex->tok_start=lex->ptr; // Skip first ` while ((c=yyGet()) && state_map[c] != STATE_USER_VARIABLE_DELIMITER && c != (uchar) NAMES_SEP_CHAR) ; yylval->lex_str=get_token(lex,yyLength()); if (lex->convert_set) lex->convert_set->convert((char*) yylval->lex_str.str,lex->yytoklen); if (state_map[c] == STATE_USER_VARIABLE_DELIMITER) - yySkip(); // Skipp end ` + yySkip(); // Skip end ` return(IDENT); case STATE_SIGNED_NUMBER: // Incomplete signed number if (prev_state == STATE_OPERATOR_OR_IDENT) { - if (c == '-' && yyPeek() == '-' && isspace(yyPeek2())) + if (c == '-' && yyPeek() == '-' && + (isspace(yyPeek2()) || iscntrl(yyPeek2()))) state=STATE_COMMENT; else state= STATE_CHAR; // Must be operator @@ -657,7 +663,7 @@ int yylex(void *arg) { c = yyGet(); if (c == '-' || c == '+') - c = yyGet(); // Skipp sign + c = yyGet(); // Skip sign if (!isdigit(c)) { // No digit after sign state= STATE_CHAR; @@ -670,6 +676,21 @@ int yylex(void *arg) yylval->lex_str=get_token(lex,yyLength()); return(REAL_NUM); + case STATE_HEX_NUMBER: // Found x'hexstring' + yyGet(); // Skip ' + while (isxdigit((c = yyGet()))) ; + length=(lex->ptr - lex->tok_start); // Length of hexnum+3 + if (!(length & 1) || c != '\'') + { + return(ABORT_SYM); // Illegal hex constant + } + yyGet(); // get_token makes an unget + yylval->lex_str=get_token(lex,length); + yylval->lex_str.str+=2; // Skip x' + yylval->lex_str.length-=3; // Don't count x' and last ' + lex->yytoklen-=3; + return (HEX_NUM); + case STATE_CMP_OP: // Incomplete comparison operator if (state_map[yyPeek()] == STATE_CMP_OP || state_map[yyPeek()] == STATE_LONG_CMP_OP) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 372e4814910..3b75eb3db71 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -65,6 +65,7 @@ enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, STATE_FOUND_IDENT, STATE_SIGNED_NUMBER, STATE_REAL, + STATE_HEX_NUMBER, STATE_CMP_OP, STATE_LONG_CMP_OP, STATE_STRING, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a978e9ae857..0efa4e0ad83 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -133,6 +133,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token BINLOG_SYM %token EVENTS_SYM +%token ABORT_SYM %token ACTION %token AGGREGATE_SYM %token ALL @@ -3036,7 +3037,7 @@ option_value: | SQL_SLAVE_SKIP_COUNTER equal ULONG_NUM { pthread_mutex_lock(&LOCK_slave); - if(slave_running) + if (slave_running) send_error(¤t_thd->net, ER_SLAVE_MUST_STOP); else slave_skip_counter = $3;