diff options
author | unknown <monty@tik.mysql.fi> | 2001-03-21 01:02:22 +0200 |
---|---|---|
committer | unknown <monty@tik.mysql.fi> | 2001-03-21 01:02:22 +0200 |
commit | 6257ee7613836c397bda6c3533ca4a114d60e045 (patch) | |
tree | 8a311781a9b85fe972ca9c89a0dc75654d3b3250 | |
parent | d1782bea92ebf698cdcf898007f3b015ba502493 (diff) | |
download | mariadb-git-6257ee7613836c397bda6c3533ca4a114d60e045.tar.gz |
Added isolation levels
Added SELECT .. FOR UPDATE and SELECT .. IN SHARE MODE
Docs/manual.texi:
Updated information about SET TRANSACTION ISOLATION LEVEL
configure.in:
Upgraded version number
isam/_dbug.c:
Fixed wrong fprintf
isam/isamchk.c:
Added new error message
myisam/mi_check.c:
Added new error message
mysql-test/mysql-test-run.sh:
Don't wait too long for server start
mysys/mf_keycache.c:
Cleaned up some error messages
scripts/mysqlhotcopy.sh:
Applied patch for --resetmaster --resetslave
sql-bench/bench-init.pl.sh:
Fix for windows
sql/handler.cc:
Added isolation levels and gemini spinlocks
sql/handler.h:
Added isolation levels
sql/item_strfunc.cc:
Cleanup of CONCAT_WS()
sql/lex.h:
Added isolation levels
sql/mysql_priv.h:
Added isolation levels
sql/mysqld.cc:
Added isolation levels
sql/sql_class.cc:
Added isolation levels
Moved variable initialization to different code segments
sql/sql_class.h:
Added isolation levels
sql/sql_lex.h:
Added isolation levels
sql/sql_parse.cc:
Added isolation levels
sql/sql_update.cc:
cleanup
BitKeeper/etc/logging_ok:
Logging to logging@openlogging.org accepted
-rw-r--r-- | BitKeeper/etc/logging_ok | 5 | ||||
-rw-r--r-- | Docs/manual.texi | 76 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | isam/_dbug.c | 2 | ||||
-rw-r--r-- | isam/isamchk.c | 10 | ||||
-rw-r--r-- | myisam/mi_check.c | 3 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 2 | ||||
-rw-r--r-- | mysys/mf_keycache.c | 21 | ||||
-rw-r--r-- | scripts/mysqlhotcopy.sh | 26 | ||||
-rw-r--r-- | sql-bench/bench-init.pl.sh | 15 | ||||
-rw-r--r-- | sql/handler.cc | 17 | ||||
-rw-r--r-- | sql/handler.h | 8 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 122 | ||||
-rw-r--r-- | sql/lex.h | 12 | ||||
-rw-r--r-- | sql/mysql_priv.h | 2 | ||||
-rw-r--r-- | sql/mysqld.cc | 18 | ||||
-rw-r--r-- | sql/sql_class.cc | 47 | ||||
-rw-r--r-- | sql/sql_class.h | 3 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_parse.cc | 38 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 90 |
22 files changed, 381 insertions, 142 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok index abbe1d55830..01a1261eae5 100644 --- a/BitKeeper/etc/logging_ok +++ b/BitKeeper/etc/logging_ok @@ -1,4 +1 @@ -jani@hynda.mysql.fi -heikki@donna.mysql.fi -monty@donna.mysql.fi -paul@central.snake.net +monty@tik.mysql.fi diff --git a/Docs/manual.texi b/Docs/manual.texi index 62382d89990..b8651afec34 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -9738,7 +9738,7 @@ uses: @cindex options, command-line @cindex mysqld options @node Command-line options, Option files, Automatic start, Post-installation -@subsection Command-line Options +@subsection mysqld Command-line Options @code{mysqld} accepts the following command-line options: @@ -9952,6 +9952,9 @@ Disable using thread priorities for faster response time. Socket file to use for local connections instead of default @code{/tmp/mysql.sock}. +@item transaction-isolation= @{ READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE @} +Sets the default transaction isolation level. @xref{SET TRANSACTION}. + @item -t, --tmpdir=path Path for temporary files. It may be useful if your default @code{/tmp} directory resides on a partition too small to hold temporary tables. @@ -10816,6 +10819,9 @@ This forces all function names to be treated as reserved words. @item @code{REAL} will be a synonym for @code{FLOAT} instead of a synonym of @code{DOUBLE}. +@item +The default transaction isolation level is @code{SERIALIZABLE}. +@xref{SET TRANSACTION}. @end itemize @node Differences from ANSI, Missing functions, ANSI mode, Compatibility @@ -13463,6 +13469,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run * COMMIT:: @code{BEGIN/COMMIT/ROLLBACK} syntax * LOCK TABLES:: @code{LOCK TABLES/UNLOCK TABLES} syntax * SET OPTION:: @code{SET OPTION} syntax +* SET TRANSACTION:: * GRANT:: @code{GRANT} and @code{REVOKE} syntax * CREATE INDEX:: @code{CREATE INDEX} syntax * DROP INDEX:: @code{DROP INDEX} syntax @@ -13485,7 +13492,7 @@ to restart @code{mysqld} with @code{--skip-grant-tables} to run * Number syntax:: Numbers * Hexadecimal values:: Hexadecimal values * NULL values:: @code{NULL} values -* Legal names:: Database, table, index, column and alias names +* Legal names:: Database, Table, Index, Column, and Alias Names @end menu @node String syntax, Number syntax, Literals, Literals @@ -19327,7 +19334,8 @@ SELECT [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [HAVING where_definition] [ORDER BY @{unsigned_integer | col_name | formula@} [ASC | DESC] ,...] [LIMIT [offset,] rows] - [PROCEDURE procedure_name] ] + [PROCEDURE procedure_name] + [FOR UPDATE | IN SHARE MODE]] @end example @c help end @@ -19570,6 +19578,17 @@ If you use @code{INTO DUMPFILE} instead of @code{INTO OUTFILE}, @strong{MySQL} will only write one row into the file, without any column or line terminations and without any escaping. This is useful if you want to store a blob in a file. + +@item +Note that any file created by @code{INTO OUTFILE} and @code{INTO +DUMPFILE} is going to be readable for all users! The reason is that the +@strong{MySQL} server can't create a file that is owned by anyone else +than the user it's running as (you should never run @code{mysqld} as root), +the file has to be word readable so that you can retrieve the rows. + +@item +If you are using @code{FOR UPDATE} on a table handler with page/row locks, +the examined rows will be write locked. @end itemize @findex JOIN @@ -20739,6 +20758,9 @@ write is aborted with an disk full error message. @findex SHOW TABLE STATUS @findex SHOW GRANTS @findex SHOW CREATE TABLE +@findex SHOW MASTER STATUS +@findex SHOW MASTER LOGS +@findex SHOW SLAVE STATUS @node SHOW, EXPLAIN, KILL, Reference @section @code{SHOW} Syntax (Get Information About Tables, Columns,...) @@ -22042,7 +22064,7 @@ table you will get an error (@code{ER_WARNING_NOT_COMPLETE_ROLLBACK}) as a warning. All transactional safe tables will be restored but any non-transactional table will not change. -If you are using @code{BEGIN} or @code{SET AUTO_COMMIT=0}, you +If you are using @code{BEGIN} or @code{SET AUTOCOMMIT=0}, you should use the @strong{MySQL} binary log for backups instead of the old update log; The transaction is stored in the binary log in one chunk, during @code{COMMIT}, the to ensure and @code{ROLLBACK}:ed @@ -22057,6 +22079,9 @@ a @code{COMMIT} before executing the command): @item @code{TRUNCATE} @end multitable +You can change the isolation level for transactions with +@code{SET TRANSACTION ISOLATION LEVEL ...}. @xref{SET TRANSACTION}. + @findex LOCK TABLES @findex UNLOCK TABLES @node LOCK TABLES, SET OPTION, COMMIT, Reference @@ -22162,7 +22187,7 @@ automaticly commit any active transactions before attempting to lock the tables. @findex SET OPTION -@node SET OPTION, GRANT, LOCK TABLES, Reference +@node SET OPTION, SET TRANSACTION, LOCK TABLES, Reference @section @code{SET} Syntax @example @@ -22303,6 +22328,30 @@ command when inserting an @code{AUTO_INCREMENT} value. This is mainly used with the update log. @end table +@findex ISOLATION LEVEL +@node SET TRANSACTION, GRANT, SET OPTION, Reference +@section @code{SET TRANSACTION} Syntax + +@example +SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL +[READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE] +@end example + +Sets the transaction isolation level for the global, whole session or +the next transaction. + +The default behaveour is to set the isolation level for the next (not started) +isolation level. + +If you set the @code{GLOBAL} privilege it will affect all new created threads. +You will need the @code{PROCESS} privilege to do do this. + +Setting the @code{SESSION} privilege will affect the following and all +future transactions. + +You can set the default isolation level for @code{mysqld} with +@code{--transaction-isolation=...}. @xref{Command-line options}. + @cindex privileges, granting @cindex privileges, revoking @cindex global privileges @@ -22311,7 +22360,7 @@ with the update log. @findex GRANT @findex REVOKE -@node GRANT, CREATE INDEX, SET OPTION, Reference +@node GRANT, CREATE INDEX, SET TRANSACTION, Reference @section @code{GRANT} and @code{REVOKE} Syntax @example @@ -36053,7 +36102,7 @@ direct from a remote mysql server! @code{mysqlbinlog --help} will give you more information of how to use this program! -If you are using @code{BEGIN} or @code{SET AUTO_COMMIT=0}, you must use +If you are using @code{BEGIN} or @code{SET AUTOCOMMIT=0}, you must use the @strong{MySQL} binary log for backups instead of the old update log. The binary logging is done immediately after a query completes but before @@ -42245,8 +42294,6 @@ Added @code{IDENTITY} as a synonym for @code{AUTO_INCREMENT} (like SyBase). @item Added @code{ORDER BY} syntax to @code{UPDATE} and @code{DELETE}. @item -Added @code{SELECT ... WITH UPDATE} and @code{SELECT ... IN SHARE MODE} to -get more locking options. @end itemize @node News-3.23.x, News-3.22.x, News-4.0.x, News @@ -42278,6 +42325,7 @@ users uses this code as the rest of the code and because of this we are not yet 100 % confident in this code. @menu +* News-3.23.36:: * News-3.23.35:: Changes in release 3.23.35 * News-3.23.34a:: Changes in release 3.23.34a * News-3.23.34:: Changes in release 3.23.34 @@ -42317,7 +42365,15 @@ not yet 100 % confident in this code. * News-3.23.0:: Changes in release 3.23.0 @end menu -@node News-3.23.35, News-3.23.34a, News-3.23.x, News-3.23.x +@node News-3.23.36, News-3.23.35, News-3.23.x, News-3.23.x +@appendixsubsec Changes in release 3.23.36 +@itemize @bullet +Added @code{SET TRANSACTION ISOLATION LEVEL ...} +@item +Added @code{SELECT ... FOR UPDATE}. +@end itemize + +@node News-3.23.35, News-3.23.34a, News-3.23.36, News-3.23.x @appendixsubsec Changes in release 3.23.35 @itemize @bullet @item diff --git a/configure.in b/configure.in index 6cacea83f36..494e47c99d3 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 3.23.35) +AM_INIT_AUTOMAKE(mysql, 3.23.36) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 diff --git a/isam/_dbug.c b/isam/_dbug.c index 644d0e420d6..fd0a0b46562 100644 --- a/isam/_dbug.c +++ b/isam/_dbug.c @@ -85,7 +85,7 @@ void _nisam_print_key(FILE *stream, register N_KEYSEG *keyseg, const uchar *key) key=end; break; case HA_KEYTYPE_INT24: - VOID(fprintf(stream,"%d",sint3korr(key))); + VOID(fprintf(stream,"%ld",sint3korr(key))); key=end; break; case HA_KEYTYPE_UINT24: diff --git a/isam/isamchk.c b/isam/isamchk.c index ce96655a7a5..bb9b7bfa16b 100644 --- a/isam/isamchk.c +++ b/isam/isamchk.c @@ -284,7 +284,7 @@ static struct option long_options[] = static void print_version(void) { - printf("%s Ver 5.15 for %s at %s\n",my_progname,SYSTEM_TYPE, + printf("%s Ver 5.16 for %s at %s\n",my_progname,SYSTEM_TYPE, MACHINE_TYPE); } @@ -1793,6 +1793,9 @@ my_string name; if (share->base.options & HA_OPTION_COMPRESS_RECORD) printf(" Huff tree Bits"); VOID(putchar('\n')); + if (verbose > 2 && share->base.pack_bits) + printf("- %-7d%-35s\n",share->base.pack_bits,"bit field"); + start=1; for (field=0 ; field < share->base.fields ; field++) { @@ -2806,6 +2809,11 @@ static int sort_get_next_record() } DBUG_RETURN(0); } + if (!searching) + { + print_info("Found wrong packed record at %lu", + (ulong) sort_info.start_recpos); + } try_next: pos=sort_info.start_recpos+1; searching=1; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 699f0f5ad68..4bd6747d499 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -2342,6 +2342,9 @@ static int sort_get_next_record(SORT_INFO *sort_info) } DBUG_RETURN(0); } + if (!searching) + mi_check_print_info(param,"Found wrong stored record at %s", + llstr(sort_info->start_recpos,llbuff)); try_next: pos=(sort_info->start_recpos+=MI_DYN_ALIGN_SIZE); searching=1; diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 16d26fc48b2..24b62a69b9f 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -241,7 +241,7 @@ SLAVE_MYSQLD=$MYSQLD #this can be changed later if we are doing gcov #-- wait_for_server_start () { - $MYSQLADMIN --no-defaults -u $DBUSER --silent -w2 --host=$hostname --port=$1 ping >/dev/null + $MYSQLADMIN --no-defaults -u $DBUSER --silent -O connect_timeout=10 -w2 --host=$hostname --port=$1 ping >/dev/null 2>&1 } prompt_user () diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c index 72d0d4a5e10..da02ec3da18 100644 --- a/mysys/mf_keycache.c +++ b/mysys/mf_keycache.c @@ -237,7 +237,7 @@ static inline void link_file_to_changed(SEC_LINK *next) #endif #ifndef DBUG_OFF -static void test_key_cache(char *where, my_bool lock); +static void test_key_cache(const char *where, my_bool lock); #endif @@ -622,9 +622,10 @@ int flush_key_blocks(File file, enum flush_type type) /* Test if disk-cachee is ok */ -static void test_key_cache(char *where, my_bool lock) +static void test_key_cache(const char *where, my_bool lock) { - reg1 uint i,found,error,changed; + reg1 uint i,error; + ulong found,changed; SEC_LINK *pos,**prev; if (lock) @@ -642,13 +643,13 @@ static void test_key_cache(char *where, my_bool lock) error=1; DBUG_PRINT("error", ("hash: %d pos: %lx : prev: %lx != pos->prev: %lx", - i,pos,prev,pos->prev_hash)); + i,(ulong) pos,(ulong) prev,(ulong) pos->prev_hash)); } if (((pos->diskpos/KEYCACHE_BLOCK_SIZE)+pos->file) % _my_hash_blocks != i) { DBUG_PRINT("error",("hash: %d pos: %lx : Wrong disk_buffer %ld", - i,pos,pos->diskpos)); + i,(ulong) pos,(ulong) pos->diskpos)); error=1; } } @@ -667,7 +668,7 @@ static void test_key_cache(char *where, my_bool lock) pos= _my_hash_root[i]; found=0; while (pos && found < 10) { - DBUG_PRINT("loop",("pos: %lx prev: %lx next: %lx file: %d disk_buffer: %ld", pos,pos->prev_hash,pos->next_hash,pos->file,pos->diskpos)); + DBUG_PRINT("loop",("pos: %lx prev: %lx next: %lx file: %d disk_buffer: %ld", (ulong) pos, (ulong) pos->prev_hash, (ulong) pos->next_hash, (ulong) pos->file, (ulong) pos->diskpos)); found++; pos= pos->next_hash; } } @@ -685,7 +686,9 @@ static void test_key_cache(char *where, my_bool lock) if (pos->next_used->prev_used != pos) { DBUG_PRINT("error",("pos: %lx next_used: %lx next_used->prev: %lx", - pos,pos->next_used,pos->next_used->prev_hash)); + (ulong) pos, + (ulong) pos->next_used, + (ulong) pos->next_used->prev_hash)); error=1; } pos=pos->next_used; @@ -696,7 +699,7 @@ static void test_key_cache(char *where, my_bool lock) } if (found != _my_blocks_used) { - DBUG_PRINT("error",("Found %d of %d keyblocks",found,_my_blocks_used)); + DBUG_PRINT("error",("Found %lu of %lu keyblocks",found,_my_blocks_used)); error=1; } @@ -751,7 +754,7 @@ static void test_key_cache(char *where, my_bool lock) } if (changed != 0) { - DBUG_PRINT("error",("Found %d blocks that wasn't in changed blocks", + DBUG_PRINT("error",("Found %lu blocks that wasn't in changed blocks", changed)); error=1; } diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index bf857c67cea..346ceb55d73 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -36,7 +36,7 @@ WARNING: THIS IS VERY MUCH A FIRST-CUT ALPHA. Comments/patches welcome. # Documentation continued at end of file -my $VERSION = "1.10"; +my $VERSION = "1.11"; my $opt_tmpdir = $ENV{TMPDIR} || "/tmp"; @@ -65,6 +65,8 @@ Usage: $0 db_name [new_db_name | directory] --suffix=# suffix for names of copied databases --checkpoint=# insert checkpoint entry into specified db.table --flushlog flush logs once all tables are locked + --resetmaster reset the binlog once all tables are locked + --resetslave reset the master.info once all tables are locked --tmpdir=# temporary directory (instead of $opt_tmpdir) Try 'perldoc $0 for more complete documentation' @@ -100,6 +102,8 @@ GetOptions( \%opt, "suffix=s", "checkpoint=s", "flushlog", + "resetmaster", + "resetslave", "tmpdir|t=s", "dryrun|n", ) or usage("Invalid option"); @@ -369,6 +373,8 @@ if ( $opt{dryrun} ) { print "LOCK TABLES $hc_locks\n"; print "FLUSH TABLES /*!32323 $hc_tables */\n"; print "FLUSH LOGS\n" if ( $opt{flushlog} ); + print "RESET MASTER\n" if ( $opt{resetmaster} ); + print "RESET SLAVE\n" if ( $opt{resetslave} ); } else { my $start = time; @@ -381,6 +387,8 @@ else { $dbh->do("FLUSH TABLES /*!32323 $hc_tables */"); printf "Flushed tables ($hc_tables) in %d seconds.\n", time-$start unless $opt{quiet}; $dbh->do( "FLUSH LOGS" ) if ( $opt{flushlog} ); + $dbh->do( "RESET MASTER" ) if ( $opt{resetmaster} ); + $dbh->do( "RESET SLAVE" ) if ( $opt{resetslave} ); } my @failed = (); @@ -658,6 +666,18 @@ of keeping the backup directory after the copy successfully completes. Rotate the log files by executing "FLUSH LOGS" after all tables are locked, and before they are copied. +=item --resetmaster + +Reset the bin-log by executing "RESET MASTER" after all tables are +locked, and before they are copied. Usefull if you are recovering a +slave in a replication setup. + +=item --resetslave + +Reset the master.info by executing "RESET SLAVE" after all tables are +locked, and before they are copied. Usefull if you are recovering a +server in a mutual replication setup. + =item --regexp pattern Copy all databases with names matching the pattern @@ -742,6 +762,7 @@ Study the code inside this script and only rely on it if I<you> believe that it does the right thing for you. Patches adding bug fixes, documentation and new features are welcome. +Please send these to internals@mysql.com. =head1 TO DO @@ -780,3 +801,6 @@ Monty - working --noindex (copy only first 2048 bytes of index file) Fixes for --method=scp Ask Bjoern Hansen - Cleanup code to fix a few bugs and enable -w again. + +Emil S. Hansen - Added resetslave and resetmaster. + diff --git a/sql-bench/bench-init.pl.sh b/sql-bench/bench-init.pl.sh index 165b15a0ede..c316bae1e4d 100644 --- a/sql-bench/bench-init.pl.sh +++ b/sql-bench/bench-init.pl.sh @@ -152,8 +152,9 @@ sub merge_limits { foreach $name (split(",",$cmp)) { - $tmp_server= get_server($name,$opt_host, $opt_database, - $opt_odbc) || die "Unknown SQL server: $name\n"; + $tmp_server= (get_server($name,$opt_host, $opt_database, + $opt_odbc,machine_part()) + || die "Unknown SQL server: $name\n"); $limits=$tmp_server->{'limits'}; %new_limits=(); foreach $limit (keys(%$limits)) @@ -365,11 +366,13 @@ sub print_time sub machine_part { - my ($name); + my ($name,$orig); return $opt_machine if (length($opt_machine)); # Specified by user - $name=machine(); - $name="win9$1" if ($name =~ /win.*9(\d)/i); - $name="NT_$1" if ($name =~ /Windows NT.*(\d+\.\d+)/i); +# Specified by user + $orig=$name=machine(); + $name="win9$1" if ($orig =~ /win.*9(\d)/i); + $name="NT_$1" if ($orig =~ /Windows NT.*(\d+\.\d+)/i); + $name="win2k" if ($orig =~ /Windows 2000/i); $name =~ s/\s+/_/g; # Make the filenames easier to parse $name =~ s/-/_/g; $name =~ s/\//_/g; diff --git a/sql/handler.cc b/sql/handler.cc index 96c19c904fe..5216941f473 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -59,6 +59,10 @@ const char *ha_row_type[] = { TYPELIB ha_table_typelib= {array_elements(ha_table_type)-4,"", ha_table_type+1}; +const char *tx_isolation_names[] = +{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE"}; +TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names),"", + tx_isolation_names}; /* Use other database handler if databasehandler is not incompiled */ @@ -203,6 +207,7 @@ int ha_autocommit_or_rollback(THD *thd, int error) } else (void) ha_rollback_stmt(thd); + thd->tx_isolation=thd->session_tx_isolation; } #endif DBUG_RETURN(error); @@ -248,6 +253,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans) #endif if (error && trans == &thd->transaction.all && mysql_bin_log.is_open()) sql_print_error("Error: Got error during commit; Binlog is not up to date!"); + thd->tx_isolation=thd->session_tx_isolation; } #endif // using transactions DBUG_RETURN(error); @@ -286,11 +292,22 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans) reinit_io_cache(&thd->transaction.trans_log, WRITE_CACHE, (my_off_t) 0, 0, 1); thd->transaction.trans_log.end_of_file= max_binlog_cache_size; + thd->tx_isolation=thd->session_tx_isolation; } #endif /* USING_TRANSACTIONS */ DBUG_RETURN(error); } +void ha_set_spin_retries(uint retries) +{ +#ifdef HAVE_GEMINI_DB + if (!gemini_skip) + { + gemini_set_option_long(GEM_OPTID_SPIN_RETRIES, retries); + } +#endif /* HAVE_GEMINI_DB */ +} + bool ha_flush_logs() { diff --git a/sql/handler.h b/sql/handler.h index 1c8a83ac9ed..463eef20ee4 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -108,7 +108,7 @@ enum db_type { DB_TYPE_UNKNOWN=0,DB_TYPE_DIAB_ISAM=1, DB_TYPE_HASH,DB_TYPE_MISAM,DB_TYPE_PISAM, DB_TYPE_RMS_ISAM, DB_TYPE_HEAP, DB_TYPE_ISAM, DB_TYPE_MRG_ISAM, DB_TYPE_MYISAM, DB_TYPE_MRG_MYISAM, - DB_TYPE_BERKELEY_DB, DB_TYPE_INNOBASE, + DB_TYPE_BERKELEY_DB, DB_TYPE_INNOBASE, DB_TYPE_GEMINI, DB_TYPE_DEFAULT }; enum row_type { ROW_TYPE_DEFAULT, ROW_TYPE_FIXED, ROW_TYPE_DYNAMIC, @@ -127,6 +127,9 @@ typedef struct st_thd_trans { void *gemini_tid; } THD_TRANS; +enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED, + ISO_REPEATABLE_READ, ISO_SERIALIZABLE}; + typedef struct st_ha_create_information { ulong table_options; @@ -310,7 +313,7 @@ public: /* Some extern variables used with handlers */ extern const char *ha_row_type[]; -extern TYPELIB ha_table_typelib; +extern TYPELIB ha_table_typelib, tx_isolation_typelib; /* Wrapper functions */ #define ha_commit_stmt(thd) (ha_commit_trans((thd), &((thd)->transaction.stmt))) @@ -332,5 +335,6 @@ void ha_key_cache(void); int ha_commit_trans(THD *thd, THD_TRANS *trans); int ha_rollback_trans(THD *thd, THD_TRANS *trans); int ha_autocommit_or_rollback(THD *thd, int error); +void ha_set_spin_retries(uint retries); bool ha_flush_logs(void); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ec47f42f2ec..1ddff29783b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -218,77 +218,75 @@ String *Item_func_concat_ws::val_str(String *str) goto null; use_as_buff= &tmp_value; - str->length(0); + str->length(0); // QQ; Should be removed res=str; // Skip until non-null and non-empty argument is found. // If not, return the empty string - for (i=0; !(res= args[i]->val_str(str)) || !res->length(); i++) - { - if ((i + 1) == arg_count) - return &empty_string; - } + for (i=0; + !(res= args[i]->val_str(str)) || !res->length() && i < arg_count; + i++) ; + if (i == arg_count) + return &empty_string; for (i++; i < arg_count ; i++) { if (!(res2= args[i]->val_str(use_as_buff)) || !res2->length()) - continue; - else + continue; // Skipp NULL and empty string + + if (res->length() + sep_str->length() + res2->length() > + max_allowed_packet) + goto null; // Error check + if (res->alloced_length() >= + res->length() + sep_str->length() + res2->length()) + { // Use old buffer + res->append(*sep_str); // res->length() > 0 always + res->append(*res2); + use_as_buff= &tmp_value; + } + else if (str->alloced_length() >= + res->length() + sep_str->length() + res2->length()) { - if (res->length() + sep_str->length() + res2->length() > - max_allowed_packet) - goto null; // Error check - if (res->alloced_length() >= - res->length() + sep_str->length() + res2->length()) - { // Use old buffer - res->append(*sep_str); // res->length() > 0 always - res->append(*res2); - use_as_buff= &tmp_value; - } - else if (str->alloced_length() >= - res->length() + sep_str->length() + res2->length()) - { - str->copy(*res); - str->append(*sep_str); - str->append(*res2); - res=str; - use_as_buff= &tmp_value; - } - else if (res == &tmp_value) - { - if ((res->length() && res->append(*sep_str)) || res->append(*res2)) - goto null; // Must be a blob - } - else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() && - res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length()) - { - /* - This happens really seldom: - In this case res2 is sub string of tmp_value. We will - now work in place in tmp_value to set it to res | res2 - */ - /* Chop the last characters in tmp_value that isn't in res2 */ - tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) + - res2->length()); - /* Place res2 at start of tmp_value, remove chars before res2 */ - if (res->append(*sep_str)) - goto null; - if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()), - *res)) - goto null; - res= &tmp_value; - use_as_buff=str; // Put next arg here - } - else - { // Two big const strings - if (tmp_value.alloc(max_length) || - tmp_value.copy(*res) || - tmp_value.append(*sep_str) || - tmp_value.append(*res2)) - goto null; - res= &tmp_value; - use_as_buff=str; - } + str->copy(*res); + str->append(*sep_str); + str->append(*res2); + res=str; + use_as_buff= &tmp_value; + } + else if (res == &tmp_value) + { + if ((res->length() && res->append(*sep_str)) || res->append(*res2)) + goto null; // Must be a blob + } + else if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() && + res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length()) + { + /* + This happens really seldom: + In this case res2 is sub string of tmp_value. We will + now work in place in tmp_value to set it to res | res2 + */ + /* Chop the last characters in tmp_value that isn't in res2 */ + tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) + + res2->length()); + /* Place res2 at start of tmp_value, remove chars before res2 */ + if (res->append(*sep_str)) + goto null; + if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()), + *res)) + goto null; + res= &tmp_value; + use_as_buff=str; // Put next arg here + } + else + { // Two big const strings + if (tmp_value.alloc(max_length) || + tmp_value.copy(*res) || + tmp_value.append(*sep_str) || + tmp_value.append(*res2)) + goto null; + res= &tmp_value; + use_as_buff=str; } } return res; diff --git a/sql/lex.h b/sql/lex.h index 6f030aa524d..898110f8d15 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -86,6 +86,7 @@ static SYMBOL symbols[] = { { "COLUMNS", SYM(COLUMNS),0,0}, { "COMMENT", SYM(COMMENT_SYM),0,0}, { "COMMIT", SYM(COMMIT_SYM),0,0}, + { "COMMITTED", SYM(COMMITTED_SYM),0,0}, { "COMPRESSED", SYM(COMPRESSED_SYM),0,0}, { "CONSTRAINT", SYM(CONSTRAINT),0,0}, { "CREATE", SYM(CREATE),0,0}, @@ -144,6 +145,8 @@ static SYMBOL symbols[] = { { "FULL", SYM(FULL),0,0}, { "FULLTEXT", SYM(FULLTEXT_SYM),0,0}, { "FUNCTION", SYM(UDF_SYM),0,0}, + { "GEMINI", SYM(GEMINI_SYM),0,0}, + { "GLOBAL", SYM(GLOBAL_SYM),0,0}, { "GRANT", SYM(GRANT),0,0}, { "GRANTS", SYM(GRANTS),0,0}, { "GROUP", SYM(GROUP),0,0}, @@ -174,6 +177,7 @@ static SYMBOL symbols[] = { { "INTO", SYM(INTO),0,0}, { "IF", SYM(IF),0,0}, { "IS", SYM(IS),0,0}, + { "ISOLATION", SYM(ISOLATION),0,0}, { "ISAM", SYM(ISAM_SYM),0,0}, { "JOIN", SYM(JOIN_SYM),0,0}, { "KEY", SYM(KEY_SYM),0,0}, @@ -182,6 +186,7 @@ static SYMBOL symbols[] = { { "LAST_INSERT_ID", SYM(LAST_INSERT_ID),0,0}, { "LEADING", SYM(LEADING),0,0}, { "LEFT", SYM(LEFT),0,0}, + { "LEVEL", SYM(LEVEL_SYM),0,0}, { "LIKE", SYM(LIKE),0,0}, { "LINES", SYM(LINES),0,0}, { "LIMIT", SYM(LIMIT),0,0}, @@ -212,6 +217,7 @@ static SYMBOL symbols[] = { { "MIN_ROWS", SYM(MIN_ROWS),0,0}, { "MINUTE", SYM(MINUTE_SYM),0,0}, { "MINUTE_SECOND", SYM(MINUTE_SECOND_SYM),0,0}, + { "MODE", SYM(MODE_SYM),0,0}, { "MODIFY", SYM(MODIFY_SYM),0,0}, { "MONTH", SYM(MONTH_SYM),0,0}, { "MRG_MYISAM", SYM(MERGE_SYM),0,0}, @@ -252,6 +258,7 @@ static SYMBOL symbols[] = { { "RENAME", SYM(RENAME),0,0}, { "REPAIR", SYM(REPAIR),0,0}, { "REPLACE", SYM(REPLACE),0,0}, + { "REPEATABLE", SYM(REPEATABLE_SYM),0,0}, { "RESET", SYM(RESET_SYM),0,0}, { "RESTORE", SYM(RESTORE_SYM),0,0}, { "RESTRICT", SYM(RESTRICT),0,0}, @@ -264,7 +271,10 @@ static SYMBOL symbols[] = { { "ROWS", SYM(ROWS_SYM),0,0}, { "SECOND", SYM(SECOND_SYM),0,0}, { "SELECT", SYM(SELECT_SYM),0,0}, + { "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0}, + { "SESSION", SYM(SESSION_SYM),0,0}, { "SET", SYM(SET),0,0}, + { "SHARE", SYM(SHARE_SYM),0,0}, { "SHOW", SYM(SHOW),0,0}, { "SHUTDOWN", SYM(SHUTDOWN),0,0}, { "SLAVE", SYM(SLAVE),0,0}, @@ -305,9 +315,11 @@ static SYMBOL symbols[] = { { "TINYTEXT", SYM(TINYTEXT),0,0}, { "TINYINT", SYM(TINYINT),0,0}, { "TRAILING", SYM(TRAILING),0,0}, + { "TRANSACTION", SYM(TRANSACTION_SYM),0,0}, { "TRUNCATE", SYM(TRUNCATE_SYM),0,0}, { "TO", SYM(TO_SYM),0,0}, { "TYPE", SYM(TYPE_SYM),0,0}, + { "UNCOMMITTED", SYM(UNCOMMITTED_SYM),0,0}, { "UNION", SYM(UNION_SYM),0,0}, { "UNIQUE", SYM(UNIQUE_SYM),0,0}, { "UNLOCK", SYM(UNLOCK_SYM),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a975cab3c7c..1e7f939bf80 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -251,6 +251,7 @@ void kill_mysql(void); void close_connection(NET *net,uint errcode=0,bool lock=1); bool check_access(THD *thd,uint access,const char *db=0,uint *save_priv=0, bool no_grant=0); +bool check_process_priv(THD *thd=0); int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table); @@ -538,6 +539,7 @@ extern String empty_string; extern struct show_var_st init_vars[]; extern struct show_var_st status_vars[]; extern enum db_type default_table_type; +extern enum enum_tx_isolation default_tx_isolation; #ifndef __WIN__ extern pthread_t signal_thread; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index e85afd6b856..951984453f0 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -278,6 +278,7 @@ char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION; const char *first_keyword="first"; const char **errmesg; /* Error messages */ const char *myisam_recover_options_str="OFF"; +enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED; my_string mysql_unix_port=NULL,mysql_tmpdir=NULL; ulong my_bind_addr; /* the address we bind to */ DATE_FORMAT dayord; @@ -2426,7 +2427,7 @@ enum options { OPT_INNOBASE_FLUSH_LOG_AT_TRX_COMMIT, OPT_SAFE_SHOW_DB, OPT_GEMINI_SKIP, OPT_INNOBASE_SKIP, - OPT_TEMP_POOL + OPT_TEMP_POOL, OPT_TX_ISOLATION }; static struct option long_options[] = { @@ -2553,6 +2554,7 @@ static struct option long_options[] = { #ifdef __WIN__ {"standalone", no_argument, 0, (int) OPT_STANDALONE}, #endif + {"transaction-isolation", required_argument, 0, (int) OPT_TX_ISOLATION}, {"temp-pool", no_argument, 0, (int) OPT_TEMP_POOL}, {"tmpdir", required_argument, 0, 't'}, {"use-locking", no_argument, 0, (int) OPT_USE_LOCKING}, @@ -2946,6 +2948,8 @@ static void usage(void) Don't give threads different priorities.\n\ --socket=... Socket file to use for connection\n\ -t, --tmpdir=path Path for temporary files\n\ + --transaction-isolation\n\ + Default transaction isolation level\n\ --temp-pool Use a pool of temporary files\n\ -u, --user=user_name Run mysqld daemon as user\n\ -V, --version output version information and exit"); @@ -3080,6 +3084,7 @@ static void get_options(int argc,char **argv) case 'a': opt_ansi_mode=1; thd_startup_options|=OPTION_ANSI_MODE; + default_tx_isolation= ISO_SERIALIZABLE; break; case 'b': strmov(mysql_home,optarg); @@ -3455,6 +3460,17 @@ static void get_options(int argc,char **argv) charsets_dir = mysql_charsets_dir; break; #include "sslopt-case.h" + case OPT_TX_ISOLATION: + { + int type; + if ((type=find_type(optarg, &tx_isolation_typelib, 2)) <= 0) + { + fprintf(stderr,"Unknown transaction isolation type: %s\n",optarg); + exit(1); + } + default_tx_isolation= (enum_tx_isolation) (type-1); + break; + } #ifdef HAVE_BERKELEY_DB case OPT_BDB_LOG: berkeley_logdir=optarg; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 925061594a9..6ea37d8a07a 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -79,50 +79,59 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), insert_id_used(0),in_lock_tables(0), global_read_lock(0),bootstrap(0) { - proc_info="login"; - where="field list"; host=user=priv_user=db=query=ip=0; locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= query_start_used=0; query_length=col_access=0; query_error=0; -#ifdef SIGNAL_WITH_VIO_CLOSE - active_vio = 0; - pthread_mutex_init(&active_vio_lock, NULL); -#endif - server_id = ::server_id; - server_status=SERVER_STATUS_AUTOCOMMIT; next_insert_id=last_insert_id=0; open_tables=temporary_tables=0; tmp_table=0; lock=locked_tables=0; used_tables=0; + gemini_spin_retries=0; cuted_fields=sent_row_count=0L; - options=thd_startup_options; - update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; start_time=(time_t) 0; current_linfo = 0; slave_thread = 0; slave_proxy_id = 0; last_nx_table = last_nx_db = 0; + cond_count=0; + convert_set=0; + mysys_var=0; + net.vio=0; + ull=0; + system_thread=0; +#ifdef __WIN__ + real_id = 0; +#endif +#ifdef SIGNAL_WITH_VIO_CLOSE + active_vio = 0; + pthread_mutex_init(&active_vio_lock, NULL); +#endif + + /* Variables with default values */ + proc_info="login"; + where="field list"; + server_id = ::server_id; + server_status=SERVER_STATUS_AUTOCOMMIT; + update_lock_default= low_priority_updates ? TL_WRITE_LOW_PRIORITY : TL_WRITE; + options=thd_startup_options; inactive_timeout=net_wait_timeout; open_options=ha_open_options; - cond_count=0; + tx_isolation=session_tx_isolation=default_tx_isolation; command=COM_CONNECT; set_query_id=1; default_select_limit= HA_POS_ERROR; max_join_size= ((::max_join_size != ~ (ulong) 0L) ? ::max_join_size : HA_POS_ERROR); - convert_set=0; - mysys_var=0; db_access=NO_ACCESS; + + /* Initialize sub structures */ + bzero((char*) &mem_root,sizeof(mem_root)); hash_init(&user_vars, USER_VARS_HASH_SIZE, 0, 0, (hash_get_key) get_var_key, (void (*)(void*)) free_var,0); - net.vio=0; - ull=0; - system_thread=0; - bzero((char*) &mem_root,sizeof(mem_root)); #ifdef USING_TRANSACTIONS if (opt_using_transactions) { @@ -134,10 +143,6 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), transaction.trans_log.end_of_file= max_binlog_cache_size; } #endif - -#ifdef __WIN__ - real_id = 0 ; -#endif } THD::~THD() diff --git a/sql/sql_class.h b/sql/sql_class.h index 1b444598401..09bb95b516e 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -268,7 +268,8 @@ public: long dbug_thread_id; pthread_t real_id; uint current_tablenr,tmp_table,cond_count,col_access,query_length; - uint server_status,open_options; + uint server_status,open_options, gemini_spin_retries; + enum_tx_isolation tx_isolation, session_tx_isolation; char scramble[9]; bool slave_thread; bool set_query_id,locked,count_cuted_fields,some_tables_deleted; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 7f52cc3e84c..e5c8cc08a5b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -139,7 +139,9 @@ typedef struct st_lex { enum_sql_command sql_command; enum lex_states next_state; enum enum_duplicates duplicates; + enum enum_tx_isolation tx_isolation; uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default; + uint gemini_spin_retries; thr_lock_type lock_option; bool create_refs,drop_primary,drop_if_exists,local_file; bool in_comment,ignore_space,verbose; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 1884a8825ba..9cb1c9b119f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -971,7 +971,7 @@ bool do_command(THD *thd) send_ok(net); // Tell client we are alive break; case COM_PROCESS_INFO: - if (!thd->priv_user[0] && check_access(thd,PROCESS_ACL,any_db)) + if (!thd->priv_user[0] && check_process_priv(thd)) break; mysql_log.write(thd,command,NullS); mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS : @@ -984,7 +984,7 @@ bool do_command(THD *thd) break; } case COM_DEBUG: - if (check_access(thd,PROCESS_ACL,any_db)) + if (check_process_priv(thd)) break; /* purecov: inspected */ mysql_print_status(thd); mysql_log.write(thd,command,NullS); @@ -1110,12 +1110,16 @@ mysql_execute_command(void) #endif break; } - - if (lex->options & SELECT_HIGH_PRIORITY) + else { + /* + Normal select: + Change lock if we are using SELECT HIGH PRIORITY, + FOR UPDATE or IN SHARE MODE + */ TABLE_LIST *table; for (table = tables ; table ; table=table->next) - table->lock_type=TL_READ_HIGH_PRIORITY; + table->lock_type= lex->lock_option; } if (!(res=open_and_lock_tables(thd,tables))) @@ -1141,7 +1145,7 @@ mysql_execute_command(void) } case SQLCOM_PURGE: { - if(check_access(thd, PROCESS_ACL, any_db)) + if (check_process_priv(thd)) goto error; res = purge_master_logs(thd, lex->to_log); break; @@ -1174,14 +1178,14 @@ mysql_execute_command(void) } case SQLCOM_SHOW_SLAVE_STAT: { - if(check_access(thd, PROCESS_ACL, any_db)) + if (check_process_priv(thd)) goto error; res = show_master_info(thd); break; } case SQLCOM_SHOW_MASTER_STAT: { - if (check_access(thd, PROCESS_ACL, any_db)) + if (check_process_priv(thd)) goto error; res = show_binlog_info(thd); break; @@ -1414,7 +1418,7 @@ mysql_execute_command(void) DBUG_VOID_RETURN; #else { - if(check_access(thd, PROCESS_ACL, any_db)) + if (check_process_priv(thd)) goto error; res = show_binlogs(thd); break; @@ -1632,13 +1636,13 @@ mysql_execute_command(void) DBUG_VOID_RETURN; #else if ((specialflag & SPECIAL_SKIP_SHOW_DB) && - check_access(thd,PROCESS_ACL,any_db)) + check_process_priv(thd)) goto error; res= mysqld_show_dbs(thd, (lex->wild ? lex->wild->ptr() : NullS)); break; #endif case SQLCOM_SHOW_PROCESSLIST: - if (!thd->priv_user[0] && check_access(thd,PROCESS_ACL,any_db)) + if (!thd->priv_user[0] && check_process_priv(thd)) break; mysqld_list_processes(thd,thd->master_access & PROCESS_ACL ? NullS : thd->priv_user,lex->verbose); @@ -1778,6 +1782,12 @@ mysql_execute_command(void) thd->update_lock_default= ((thd->options & OPTION_LOW_PRIORITY_UPDATES) ? TL_WRITE_LOW_PRIORITY : TL_WRITE); thd->default_select_limit=lex->select_limit; + thd->tx_isolation=lex->tx_isolation; + if (thd->gemini_spin_retries != lex->gemini_spin_retries) + { + thd->gemini_spin_retries= lex->gemini_spin_retries; + ha_set_spin_retries(thd->gemini_spin_retries); + } DBUG_PRINT("info",("options: %ld limit: %ld", thd->options,(long) thd->default_select_limit)); @@ -2092,6 +2102,12 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, } +bool check_process_priv(THD *thd) +{ + return (check_access(thd ? thd : current_thd,PROCESS_ACL,any_db)); +} + + /* ** Check the privilege for all used tables. Table privileges are cached ** in the table list for GRANT checking diff --git a/sql/sql_update.cc b/sql/sql_update.cc index a4e5dea5e76..688a5cebfee 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -20,8 +20,6 @@ #include "mysql_priv.h" #include "sql_acl.h" -#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1)) - /* Return 0 if row hasn't changed */ static bool compare_record(TABLE *table, ulong query_id) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 34cdb3dbf13..2207d8834b2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -54,6 +54,7 @@ inline Item *or_or_concat(Item* A, Item* B) Key::Keytype key_type; enum db_type db_type; enum row_type row_type; + enum enum_tx_isolation tx_isolation; String *string; key_part_spec *key_part; TABLE_LIST *table_list; @@ -141,6 +142,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token CASCADE %token CHECKSUM_SYM %token CHECK_SYM +%token COMMITTED_SYM %token COLUMNS %token COLUMN_SYM %token CONSTRAINT @@ -166,6 +168,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token FROM %token FULL %token FULLTEXT_SYM +%token GEMINI_SYM +%token GEMINI_SPIN_RETRIES +%token GLOBAL_SYM %token GRANT %token GRANTS %token GREATEST_SYM @@ -183,12 +188,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token INNOBASE_SYM %token INTO %token IN_SYM +%token ISOLATION %token ISAM_SYM %token JOIN_SYM %token KEYS %token KEY_SYM %token LEADING %token LEAST_SYM +%token LEVEL_SYM %token LEX_HOSTNAME %token LIKE %token LINES @@ -244,6 +251,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token REGEXP %token RELOAD %token RENAME +%token REPEATABLE_SYM %token RESTORE_SYM %token RESTRICT %token REVOKE @@ -251,6 +259,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token ROW_FORMAT_SYM %token ROW_SYM %token SET +%token SERIALIZABLE_SYM +%token SESSION_SYM %token SHUTDOWN %token STARTING %token STATUS_SYM @@ -262,6 +272,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token TEXT_STRING %token TO_SYM %token TRAILING +%token TRANSACTION_SYM %token TYPE_SYM %token FUNC_ARG0 %token FUNC_ARG1 @@ -270,6 +281,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token UDF_RETURNS_SYM %token UDF_SONAME_SYM %token UDF_SYM +%token UNCOMMITTED_SYM %token UNION_SYM %token UNIQUE_SYM %token USAGE @@ -361,6 +373,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token MAKE_SET_SYM %token MINUTE_SECOND_SYM %token MINUTE_SYM +%token MODE_SYM %token MODIFY_SYM %token MONTH_SYM %token NOW_SYM @@ -372,6 +385,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token RIGHT %token ROUND %token SECOND_SYM +%token SHARE_SYM %token SUBSTRING %token SUBSTRING_INDEX %token TRIM @@ -484,6 +498,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %type <row_type> row_types +%type <tx_isolation> tx_isolation isolation_types + %type <udf_type> udf_func_type %type <symbol> FUNC_ARG0 FUNC_ARG1 FUNC_ARG2 FUNC_ARG3 keyword @@ -749,7 +765,8 @@ table_types: | MERGE_SYM { $$= DB_TYPE_MRG_MYISAM; } | HEAP_SYM { $$= DB_TYPE_HEAP; } | BERKELEY_DB_SYM { $$= DB_TYPE_BERKELEY_DB; } - | INNOBASE_SYM { $$= DB_TYPE_INNOBASE; } + | INNOBASE_SYM { $$= DB_TYPE_INNOBASE; } + | GEMINI_SYM { $$= DB_TYPE_GEMINI; } row_types: DEFAULT { $$= ROW_TYPE_DEFAULT; } @@ -1216,9 +1233,10 @@ select: { LEX *lex=Lex; lex->sql_command= SQLCOM_SELECT; + lex->lock_option=TL_READ; mysql_init_select(lex); } - select_options select_item_list select_into + select_options select_item_list select_into select_lock_type select_into: /* empty */ @@ -1240,13 +1258,20 @@ select_option_list: select_option: STRAIGHT_JOIN { Lex->options|= SELECT_STRAIGHT_JOIN; } - | HIGH_PRIORITY { Lex->options|= SELECT_HIGH_PRIORITY; } + | HIGH_PRIORITY { Lex->lock_option= TL_READ_HIGH_PRIORITY; } | DISTINCT { Lex->options|= SELECT_DISTINCT; } | SQL_SMALL_RESULT { Lex->options|= SELECT_SMALL_RESULT; } | SQL_BIG_RESULT { Lex->options|= SELECT_BIG_RESULT; } | SQL_BUFFER_RESULT { Lex->options|= OPTION_BUFFER_RESULT; } | ALL {} +select_lock_type: + /* empty */ + | FOR_SYM UPDATE_SYM + { Lex->lock_option= TL_WRITE; } + | IN_SYM SHARE_SYM MODE_SYM + { Lex->lock_option= TL_READ_WITH_SHARED_LOCKS; } + select_item_list: select_item_list ',' select_item | select_item @@ -2124,8 +2149,10 @@ opt_low_priority: delete: DELETE_SYM - { Lex->sql_command= SQLCOM_DELETE; Lex->options=0; - Lex->lock_option= current_thd->update_lock_default; } + { + Lex->sql_command= SQLCOM_DELETE; Lex->options=0; + Lex->lock_option= current_thd->update_lock_default; + } opt_delete_options FROM table where_clause delete_limit_clause @@ -2479,6 +2506,7 @@ keyword: | AGAINST {} | AGGREGATE_SYM {} | AUTOCOMMIT {} + | AUTO_INC {} | AVG_ROW_LENGTH {} | AVG_SYM {} | BACKUP_SYM {} @@ -2491,6 +2519,7 @@ keyword: | CHECK_SYM {} | COMMENT_SYM {} | COMMIT_SYM {} + | COMMITTED_SYM {} | COMPRESSED_SYM {} | DATA_SYM {} | DATETIME {} @@ -2510,12 +2539,16 @@ keyword: | FIXED_SYM {} | FLUSH_SYM {} | GRANTS {} + | GEMINI_SYM {} + | GLOBAL_SYM {} | HEAP_SYM {} | HOSTS_SYM {} | HOUR_SYM {} | IDENTIFIED_SYM {} + | ISOLATION {} | ISAM_SYM {} | INNOBASE_SYM {} + | LEVEL_SYM {} | LOCAL_SYM {} | LOGS_SYM {} | MAX_ROWS {} @@ -2532,6 +2565,7 @@ keyword: | MINUTE_SYM {} | MIN_ROWS {} | MODIFY_SYM {} + | MODE_SYM {} | MONTH_SYM {} | MYISAM_SYM {} | NATIONAL_SYM {} @@ -2550,6 +2584,7 @@ keyword: | RAID_TYPE {} | RELOAD {} | REPAIR {} + | REPEATABLE_SYM {} | RESET_SYM {} | RESTORE_SYM {} | ROLLBACK_SYM {} @@ -2557,6 +2592,9 @@ keyword: | ROW_FORMAT_SYM {} | ROW_SYM {} | SECOND_SYM {} + | SERIALIZABLE_SYM {} + | SESSION_SYM {} + | SHARE_SYM {} | SHUTDOWN {} | START_SYM {} | STATUS_SYM {} @@ -2564,11 +2602,13 @@ keyword: | STRING_SYM {} | TEMPORARY {} | TEXT_SYM {} + | TRANSACTION_SYM {} | TRUNCATE_SYM {} | TIMESTAMP {} | TIME_SYM {} | TYPE_SYM {} | UDF_SYM {} + | UNCOMMITTED_SYM {} | VARIABLES {} | WORK_SYM {} | YEAR_SYM {} @@ -2579,9 +2619,12 @@ keyword: set: SET opt_option { + THD *thd=current_thd; Lex->sql_command= SQLCOM_SET_OPTION; - Lex->options=current_thd->options; - Lex->select_limit=current_thd->default_select_limit; + Lex->options=thd->options; + Lex->select_limit=thd->default_select_limit; + Lex->gemini_spin_retries=thd->gemini_spin_retries; + Lex->tx_isolation=thd->tx_isolation; } option_value_list @@ -2601,6 +2644,7 @@ option_value: else Lex->options|= $1; } + | set_isolation | AUTOCOMMIT equal NUM { if (atoi($3.str) != 0) /* Test NOT AUTOCOMMIT */ @@ -2641,6 +2685,14 @@ option_value: { current_thd->next_insert_id=$3; } + | GEMINI_SPIN_RETRIES equal ULONG_NUM + { + Lex->gemini_spin_retries= $3; + } + | GEMINI_SPIN_RETRIES equal DEFAULT + { + Lex->gemini_spin_retries= 1; + } | CHAR_SYM SET IDENT { CONVERT *tmp; @@ -2702,7 +2754,7 @@ text_or_password: } set_option: - SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; } + SQL_BIG_TABLES { $$= OPTION_BIG_TABLES; } | SQL_BIG_SELECTS { $$= OPTION_BIG_SELECTS; } | SQL_LOG_OFF { $$= OPTION_LOG_OFF; } | SQL_LOG_UPDATE @@ -2724,6 +2776,28 @@ set_option: | SQL_BUFFER_RESULT { $$= OPTION_BUFFER_RESULT; } | SQL_QUOTE_SHOW_CREATE { $$= OPTION_QUOTE_SHOW_CREATE; } + +set_isolation: + GLOBAL_SYM tx_isolation + { + if (check_process_priv()) + YYABORT; + default_tx_isolation= $2; + } + | SESSION_SYM tx_isolation + { current_thd->session_tx_isolation= $2; } + | tx_isolation + { Lex->tx_isolation= $1; } + +tx_isolation: + TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types { $$=$4; } + +isolation_types: + READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; } + | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; } + | REPEATABLE_SYM READ_SYM { $$= ISO_REPEATABLE_READ; } + | SERIALIZABLE_SYM { $$= ISO_SERIALIZABLE; } + /* Lock function */ lock: |