Makefile.am:
  Auto merged
BitKeeper/etc/config:
  Auto merged
scripts/Makefile.am:
  Auto merged
sql/ha_federated.h:
  Auto merged
sql/ha_innodb.cc:
  Auto merged
sql/item.cc:
  Auto merged
sql/item_subselect.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/set_var.cc:
  Auto merged
sql/sp.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_delete.cc:
  Auto merged
sql/sql_insert.cc:
  Auto merged
sql/sql_lex.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_show.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
sql/table.cc:
  Auto merged
sql/table.h:
  Auto merged
storage/innobase/include/page0page.ic:
  Auto merged
storage/innobase/include/univ.i:
  Auto merged
storage/innobase/row/row0mysql.c:
  Auto merged
storage/innobase/row/row0sel.c:
  Auto merged
storage/myisam/mi_check.c:
  Auto merged
storage/myisam/mi_packrec.c:
  Auto merged
storage/myisam/mi_static.c:
  Auto merged
storage/myisam/myisamdef.h:
  Auto merged
storage/myisam/myisampack.c:
  Auto merged
storage/ndb/include/kernel/signaldata/SignalData.hpp:
  Auto merged
storage/ndb/include/kernel/signaldata/StartFragReq.hpp:
  Auto merged
storage/ndb/src/common/debugger/EventLogger.cpp:
  Auto merged
storage/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp:
  Auto merged
storage/ndb/src/common/debugger/signaldata/StartRec.cpp:
  Auto merged
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp:
  Auto merged
storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp:
  Auto merged
storage/ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp:
  Auto merged
storage/ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp:
  Auto merged
storage/ndb/src/kernel/main.cpp:
  Auto merged
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp:
  Auto merged
storage/ndb/src/kernel/vm/Emulator.cpp:
  Auto merged
sql/log_event.cc:
  SCCS merged
sql/sql_prepare.cc:
  SCCS merged
sql/share/errmsg.txt:
  merge
This commit is contained in:
unknown 2005-09-06 09:20:15 +02:00
commit f6c1d4191c
77 changed files with 2816 additions and 1239 deletions

View File

@ -312,6 +312,7 @@ emacs.h
extra/charset2html
extra/comp_err
extra/created_include_files
extra/innochecksum
extra/my_print_defaults
extra/mysql_install
extra/mysql_tzinfo_to_sql

View File

@ -99,12 +99,6 @@ tags:
support-files/build-tags
.PHONY: init-db bin-dist
# Test installation
test:
cd mysql-test; \
./mysql-test-run && ./mysql-test-run --ps-protocol
# Test installation. Ports are configurable from the environment.
MYSQL_TEST_MANAGER_PORT = 9305

View File

@ -1974,14 +1974,15 @@ int safe_connect(MYSQL* con, const char *host, const char *user,
const char *pass,
const char *db, int port, const char *sock)
{
int con_error = 1;
int con_error= 1;
my_bool reconnect= 1;
int i;
for (i = 0; i < MAX_CON_TRIES; ++i)
for (i= 0; i < MAX_CON_TRIES; ++i)
{
if (mysql_real_connect(con, host,user, pass, db, port, sock,
CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS))
{
con_error = 0;
con_error= 0;
break;
}
sleep(CON_RETRY_SLEEP);
@ -1990,7 +1991,7 @@ int safe_connect(MYSQL* con, const char *host, const char *user,
TODO: change this to 0 in future versions, but the 'kill' test relies on
existing behavior
*/
con->reconnect= 1;
mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect);
return con_error;
}
@ -2024,6 +2025,7 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
int* create_conn)
{
DYNAMIC_STRING ds_tmp, *ds;
my_bool reconnect= 1;
int error= 0;
/*
@ -2089,7 +2091,7 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host,
TODO: change this to 0 in future versions, but the 'kill' test relies on
existing behavior
*/
con->reconnect= 1;
mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect);
if (record)
{
@ -2368,6 +2370,7 @@ int read_line(char *buf, int size)
enum {R_NORMAL, R_Q, R_Q_IN_Q, R_SLASH_IN_Q,
R_COMMENT, R_LINE_START} state= R_LINE_START;
DBUG_ENTER("read_line");
LINT_INIT(quote);
start_lineno= *lineno;
for (; p < buf_end ;)
@ -4264,11 +4267,17 @@ int main(int argc, char **argv)
ps_protocol_enabled= ps_protocol;
break;
case Q_DISABLE_RECONNECT:
cur_con->mysql.reconnect= 0;
{
my_bool reconnect= 0;
mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
break;
}
case Q_ENABLE_RECONNECT:
cur_con->mysql.reconnect= 1;
{
my_bool reconnect= 1;
mysql_options(&cur_con->mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect);
break;
}
case Q_DISABLE_PARSING:
parsing_disabled++;
break;
@ -4284,13 +4293,16 @@ int main(int argc, char **argv)
case Q_EXIT:
abort_flag= 1;
break;
default: processed = 0; break;
default:
processed= 0;
break;
}
}
if (!processed)
{
current_line_inc = 0;
current_line_inc= 0;
switch (q->type) {
case Q_WHILE: do_block(cmd_while, q); break;
case Q_IF: do_block(cmd_if, q); break;

View File

@ -38,7 +38,7 @@ $(top_builddir)/include/mysqld_ername.h: $(top_builddir)/include/mysqld_error.h
$(top_builddir)/include/sql_state.h: $(top_builddir)/include/mysqld_error.h
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
resolve_stack_dump mysql_waitpid
resolve_stack_dump mysql_waitpid innochecksum
noinst_PROGRAMS = charset2html
# Don't update the files from bitkeeper

302
extra/innochecksum.c Normal file
View File

@ -0,0 +1,302 @@
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
InnoDB offline file checksum utility. 85% of the code in this file
was taken wholesale fron the InnoDB codebase.
The final 15% was originally written by Mark Smith of Danga
Interactive, Inc. <junior@danga.com>
Published with a permission.
*/
// needed to have access to 64 bit file functions
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
// all of these ripped from InnoDB code from MySQL 4.0.22
#define UT_HASH_RANDOM_MASK 1463735687
#define UT_HASH_RANDOM_MASK2 1653893711
#define FIL_PAGE_LSN 16
#define FIL_PAGE_FILE_FLUSH_LSN 26
#define FIL_PAGE_OFFSET 4
#define FIL_PAGE_DATA 38
#define FIL_PAGE_END_LSN_OLD_CHKSUM 8
#define FIL_PAGE_SPACE_OR_CHKSUM 0
#define UNIV_PAGE_SIZE (2 * 8192)
// command line argument to do page checks (that's it)
// another argument to specify page ranges... seek to right spot and go from there
typedef unsigned long int ulint;
typedef unsigned char byte;
/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */
ulint mach_read_from_4(byte *b) {
return( ((ulint)(b[0]) << 24)
+ ((ulint)(b[1]) << 16)
+ ((ulint)(b[2]) << 8)
+ (ulint)(b[3])
);
}
ulint
ut_fold_ulint_pair(
/*===============*/
/* out: folded value */
ulint n1, /* in: ulint */
ulint n2) /* in: ulint */
{
return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1)
^ UT_HASH_RANDOM_MASK) + n2);
}
ulint
ut_fold_binary(
/*===========*/
/* out: folded value */
byte* str, /* in: string of bytes */
ulint len) /* in: length */
{
ulint i;
ulint fold = 0;
for (i = 0; i < len; i++) {
fold = ut_fold_ulint_pair(fold, (ulint)(*str));
str++;
}
return(fold);
}
ulint
buf_calc_page_new_checksum(
/*=======================*/
/* out: checksum */
byte* page) /* in: buffer page */
{
ulint checksum;
/* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
are written outside the buffer pool to the first pages of data
files, we have to skip them in the page checksum calculation.
We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
checksum is stored, and also the last 8 bytes of page because
there we store the old formula checksum. */
checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
+ ut_fold_binary(page + FIL_PAGE_DATA,
UNIV_PAGE_SIZE - FIL_PAGE_DATA
- FIL_PAGE_END_LSN_OLD_CHKSUM);
checksum = checksum & 0xFFFFFFFF;
return(checksum);
}
ulint
buf_calc_page_old_checksum(
/*=======================*/
/* out: checksum */
byte* page) /* in: buffer page */
{
ulint checksum;
checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
checksum = checksum & 0xFFFFFFFF;
return(checksum);
}
int main(int argc, char **argv) {
FILE *f; // our input file
byte *p; // storage of pages read
int bytes; // bytes read count
ulint ct; // current page number (0 based)
int now; // current time
int lastt; // last time
ulint oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; // ulints for checksum storage
struct stat64 st; // for stat, if you couldn't guess
unsigned long long int size; // size of file (has to be 64 bits)
ulint pages; // number of pages in file
ulint start_page = 0, end_page = 0, use_end_page = 0; // for starting and ending at certain pages
int just_count = 0; // if true, just print page count
int verbose = 0;
int debug = 0;
int c;
int fd;
// remove arguments
while ((c = getopt(argc, argv, "cvds:e:p:")) != -1) {
switch (c) {
case 'v':
verbose = 1;
break;
case 'c':
just_count = 1;
break;
case 's':
start_page = atoi(optarg);
break;
case 'e':
end_page = atoi(optarg);
use_end_page = 1;
break;
case 'p':
start_page = atoi(optarg);
end_page = atoi(optarg);
use_end_page = 1;
break;
case 'd':
debug = 1;
break;
case ':':
fprintf(stderr, "option -%c requires an argument\n", optopt);
return 1;
break;
case '?':
fprintf(stderr, "unrecognized option: -%c\n", optopt);
return 1;
break;
}
}
// debug implies verbose...
if (debug) verbose = 1;
// make sure we have the right arguments
if (optind >= argc) {
printf("InnoDB offline file checksum utility.\n");
printf("usage: %s [-c] [-s <start page>] [-e <end page>] [-p <page>] [-v] [-d] <filename>\n", argv[0]);
printf("\t-c\tprint the count of pages in the file\n");
printf("\t-s n\tstart on this page number (0 based)\n");
printf("\t-e n\tend at this page number (0 based)\n");
printf("\t-p n\tcheck only this page (0 based)\n");
printf("\t-v\tverbose (prints progress every 5 seconds)\n");
printf("\t-d\tdebug mode (prints checksums for each page)\n");
return 1;
}
// stat the file to get size and page count
if (stat64(argv[optind], &st)) {
perror("error statting file");
return 1;
}
size = st.st_size;
pages = size / UNIV_PAGE_SIZE;
if (just_count) {
printf("%lu\n", pages);
return 0;
} else if (verbose) {
printf("file %s = %llu bytes (%lu pages)...\n", argv[1], size, pages);
printf("checking pages in range %lu to %lu\n", start_page, use_end_page ? end_page : (pages - 1));
}
// open the file for reading
f = fopen64(argv[optind], "r");
if (!f) {
perror("error opening file");
return 1;
}
// seek to the necessary position
if (start_page) {
fd = fileno(f);
if (!fd) {
perror("unable to obtain file descriptor number");
return 1;
}
if (lseek64(fd, start_page * UNIV_PAGE_SIZE, SEEK_SET) != (start_page * UNIV_PAGE_SIZE)) {
perror("unable to seek to necessary offset");
return 1;
}
}
// allocate buffer for reading (so we don't realloc every time)
p = (byte *)malloc(UNIV_PAGE_SIZE);
// main checksumming loop
ct = start_page;
lastt = 0;
while (!feof(f)) {
bytes = fread(p, 1, UNIV_PAGE_SIZE, f);
if (!bytes && feof(f)) return 0;
if (bytes != UNIV_PAGE_SIZE) {
fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE);
return 1;
}
// check the "stored log sequence numbers"
logseq = mach_read_from_4(p + FIL_PAGE_LSN + 4);
logseqfield = mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4);
if (debug)
printf("page %lu: log sequence number: first = %lu; second = %lu\n", ct, logseq, logseqfield);
if (logseq != logseqfield) {
fprintf(stderr, "page %lu invalid (fails log sequence number check)\n", ct);
return 1;
}
// check old method of checksumming
oldcsum = buf_calc_page_old_checksum(p);
oldcsumfield = mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
if (debug)
printf("page %lu: old style: calculated = %lu; recorded = %lu\n", ct, oldcsum, oldcsumfield);
if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum) {
fprintf(stderr, "page %lu invalid (fails old style checksum)\n", ct);
return 1;
}
// now check the new method
csum = buf_calc_page_new_checksum(p);
csumfield = mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM);
if (debug)
printf("page %lu: new style: calculated = %lu; recorded = %lu\n", ct, csum, csumfield);
if (csumfield != 0 && csum != csumfield) {
fprintf(stderr, "page %lu invalid (fails new style checksum)\n", ct);
return 1;
}
// end if this was the last page we were supposed to check
if (use_end_page && (ct >= end_page))
return 0;
// do counter increase and progress printing
ct++;
if (verbose) {
if (ct % 64 == 0) {
now = time(0);
if (!lastt) lastt = now;
if (now - lastt >= 1) {
printf("page %lu okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100);
lastt = now;
}
}
}
}
return 0;
}

View File

@ -146,7 +146,7 @@ enum mysql_option
MYSQL_OPT_WRITE_TIMEOUT, MYSQL_OPT_USE_RESULT,
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT
};
struct st_mysql_options {

View File

@ -16,103 +16,103 @@ create view v1Aa as select * from t1aA;
create view v2aA as select * from v1aA;
create view v3Aa as select v2Aa.col1 from v2aA,t2Aa where v2Aa.col1 = t2aA.col1;
update v2aA set col1 = (select max(col1) from v1Aa);
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation UPDATE on table 'v2aA'.
update v2Aa set col1 = (select max(col1) from t1Aa);
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation UPDATE on table 'v2Aa'.
update v2aA set col1 = (select max(col1) from v2Aa);
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v1aA) where v2aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 'v2aA'.
update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v1Aa) where t1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation UPDATE on table 't1aA'.
update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v1aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v1aA' for update in FROM clause
update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from v1aA) where v2Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 't2Aa'.
update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v1Aa) where t1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation UPDATE on table 't2Aa'.
update t2Aa,v1aA set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 't2Aa'.
update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from t1aA) where v2aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v2aA'.
update t1Aa,t2Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: You can't specify target table 't1Aa' for update in FROM clause
update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from t1Aa) where v1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v1aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 'v1aA'.
update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from t1aA) where v2Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: You can't specify target table 't2Aa' for update in FROM clause
update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: You can't specify target table 't2Aa' for update in FROM clause
update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from t1Aa) where v1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: You can't specify target table 't2Aa' for update in FROM clause
update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v2aA) where t1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 't1aA'.
update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v2Aa) where v1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v1aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation UPDATE on table 'v1aA'.
update t2Aa,v2aA set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 't2Aa'.
update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v2aA) where t1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 't2Aa'.
update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from v2Aa) where v1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation UPDATE on table 't2Aa'.
update v3aA set v3Aa.col1 = (select max(col1) from v1aA);
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation UPDATE on table 'v3aA'.
update v3aA set v3Aa.col1 = (select max(col1) from t1aA);
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: The definition of table 'v3aA' prevents operation UPDATE on table 'v3aA'.
update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation UPDATE on table 'v3aA'.
update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v3aA' for update in FROM clause
delete from v2Aa where col1 = (select max(col1) from v1Aa);
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 'v2Aa'.
delete from v2aA where col1 = (select max(col1) from t1Aa);
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation DELETE on table 'v2aA'.
delete from v2Aa where col1 = (select max(col1) from v2aA);
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v2Aa' for update in FROM clause
delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation DELETE on table 'v2aA'.
delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 't1Aa'.
delete v1aA from v1Aa,t2Aa where (select max(col1) from v1aA) > 0 and v1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v1aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v1Aa' for update in FROM clause
delete v2aA from v2Aa,t2Aa where (select max(col1) from t1Aa) > 0 and v2aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation DELETE on table 'v2Aa'.
delete t1aA from t1Aa,t2Aa where (select max(col1) from t1aA) > 0 and t1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: You can't specify target table 't1Aa' for update in FROM clause
delete v1aA from v1Aa,t2Aa where (select max(col1) from t1aA) > 0 and v1aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v1aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation DELETE on table 'v1Aa'.
delete v2Aa from v2aA,t2Aa where (select max(col1) from v2Aa) > 0 and v2aA.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
delete t1Aa from t1aA,t2Aa where (select max(col1) from v2Aa) > 0 and t1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation DELETE on table 't1aA'.
delete v1Aa from v1aA,t2Aa where (select max(col1) from v2aA) > 0 and v1Aa.col1 = t2aA.col1;
ERROR HY000: You can't specify target table 'v1aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation DELETE on table 'v1aA'.
insert into v2Aa values ((select max(col1) from v1aA));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation INSERT on table 'v2Aa'.
insert into t1aA values ((select max(col1) from v1Aa));
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation INSERT on table 't1aA'.
insert into v2aA values ((select max(col1) from v1aA));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v1aA' prevents operation INSERT on table 'v2aA'.
insert into v2Aa values ((select max(col1) from t1Aa));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation INSERT on table 'v2Aa'.
insert into t1aA values ((select max(col1) from t1Aa));
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: You can't specify target table 't1aA' for update in FROM clause
insert into v2aA values ((select max(col1) from t1aA));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation INSERT on table 'v2aA'.
insert into v2Aa values ((select max(col1) from v2aA));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v2Aa' for update in FROM clause
insert into t1Aa values ((select max(col1) from v2Aa));
ERROR HY000: You can't specify target table 't1aa' for update in FROM clause
ERROR HY000: The definition of table 'v2Aa' prevents operation INSERT on table 't1Aa'.
insert into v2aA values ((select max(col1) from v2Aa));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
ERROR HY000: You can't specify target table 'v2aA' for update in FROM clause
insert into v3Aa (col1) values ((select max(col1) from v1Aa));
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: The definition of table 'v1Aa' prevents operation INSERT on table 'v3Aa'.
insert into v3aA (col1) values ((select max(col1) from t1aA));
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: The definition of table 'v3aA' prevents operation INSERT on table 'v3aA'.
insert into v3Aa (col1) values ((select max(col1) from v2aA));
ERROR HY000: You can't specify target table 'v3aa' for update in FROM clause
ERROR HY000: The definition of table 'v2aA' prevents operation INSERT on table 'v3Aa'.
drop view v3aA,v2Aa,v1aA;
drop table t1Aa,t2Aa;
create table t1Aa (col1 int);

View File

@ -1,5 +1,5 @@
prepare stmt1 from ' show full processlist ';
execute stmt1;
Id User Host db Command Time State Info
number root localhost test Execute time NULL show full processlist
number root localhost test Query time NULL show full processlist
deallocate prepare stmt1;

View File

@ -29,3 +29,14 @@ drop table if exists t1,t2,t11;
show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1658 # # master-bin.000001 Yes Yes test.t1 0 0 1658 # None 0 No #
create table t1 (ts timestamp);
set one_shot time_zone='met';
insert into t1 values('2005-08-12 00:00:00');
set one_shot time_zone='met';
select * from t1;
ts
2005-08-12 00:00:00
set one_shot time_zone='met';
select * from t1;
ts
2005-08-12 00:00:00

View File

@ -0,0 +1,364 @@
create procedure p1()
begin
prepare stmt from "select 1";
execute stmt;
execute stmt;
execute stmt;
deallocate prepare stmt;
end|
call p1()|
1
1
1
1
1
1
call p1()|
1
1
1
1
1
1
call p1()|
1
1
1
1
1
1
drop procedure p1|
create procedure p1()
begin
execute stmt;
end|
prepare stmt from "call p1()"|
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
call p1()|
ERROR HY000: Recursive stored routines are not allowed.
call p1()|
ERROR HY000: Recursive stored routines are not allowed.
call p1()|
ERROR HY000: Recursive stored routines are not allowed.
drop procedure p1|
create procedure p1()
begin
prepare stmt from "create procedure p2() begin select 1; end";
execute stmt;
deallocate prepare stmt;
end|
call p1()|
ERROR HY000: This command is not supported in the prepared statement protocol yet
call p1()|
ERROR HY000: This command is not supported in the prepared statement protocol yet
drop procedure p1|
create procedure p1()
begin
prepare stmt from "drop procedure p2";
execute stmt;
deallocate prepare stmt;
end|
call p1()|
ERROR HY000: This command is not supported in the prepared statement protocol yet
call p1()|
ERROR HY000: This command is not supported in the prepared statement protocol yet
drop procedure p1|
create procedure p1()
begin
prepare stmt_drop from "drop table if exists t1";
execute stmt_drop;
prepare stmt from "create table t1 (a int)";
execute stmt;
insert into t1 (a) values (1);
select * from t1;
deallocate prepare stmt;
deallocate prepare stmt_drop;
end|
call p1()|
a
1
Warnings:
Note 1051 Unknown table 't1'
call p1()|
a
1
drop procedure p1|
create procedure p1()
begin
set @tab_name=concat("tab_", replace(curdate(), '-', '_'));
set @drop_sql=concat("drop table if exists ", @tab_name);
set @create_sql=concat("create table ", @tab_name, " (a int)");
set @insert_sql=concat("insert into ", @tab_name, " values (1), (2), (3)");
set @select_sql=concat("select * from ", @tab_name);
select @tab_name;
select @drop_sql;
select @create_sql;
select @insert_sql;
select @select_sql;
prepare stmt_drop from @drop_sql;
execute stmt_drop;
prepare stmt from @create_sql;
execute stmt;
prepare stmt from @insert_sql;
execute stmt;
prepare stmt from @select_sql;
execute stmt;
execute stmt_drop;
deallocate prepare stmt;
deallocate prepare stmt_drop;
end|
call p1()|
call p1()|
drop procedure p1|
create procedure p1()
begin
prepare stmt_drop from "drop table if exists t1";
execute stmt_drop;
prepare stmt from "create table t1 (a int)";
execute stmt;
deallocate prepare stmt;
deallocate prepare stmt_drop;
end|
drop function if exists f1|
create function f1(a int) returns int
begin
call p1();
return 1;
end|
select f1(0)|
ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
select f1(f1(0))|
ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
select f1(f1(f1(0)))|
ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
drop function f1|
drop procedure p1|
create procedure p1()
begin
drop table if exists t1;
create table t1 (id integer not null primary key,
name varchar(20) not null);
insert into t1 (id, name) values (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
prepare stmt from "select name from t1";
execute stmt;
select name from t1;
execute stmt;
prepare stmt from
"select name from t1 where name=(select name from t1 where id=2)";
execute stmt;
select name from t1 where name=(select name from t1 where id=2);
execute stmt;
end|
call p1()|
name
aaa
bbb
ccc
name
aaa
bbb
ccc
name
aaa
bbb
ccc
name
bbb
name
bbb
name
bbb
call p1()|
name
aaa
bbb
ccc
name
aaa
bbb
ccc
name
aaa
bbb
ccc
name
bbb
name
bbb
name
bbb
drop procedure p1|
prepare stmt from "select * from t1"|
create procedure p1()
begin
execute stmt;
deallocate prepare stmt;
end|
call p1()|
id name
1 aaa
2 bbb
3 ccc
call p1()|
ERROR HY000: Unknown prepared statement handler (stmt) given to EXECUTE
drop procedure p1|
create procedure p1()
begin
declare a char(10);
set a="sp-variable";
set @a="mysql-variable";
prepare stmt from "select 'dynamic sql:', @a, a";
execute stmt;
end|
call p1()|
ERROR 42S22: Unknown column 'a' in 'field list'
call p1()|
ERROR 42S22: Unknown column 'a' in 'field list'
drop procedure p1|
create procedure p1()
begin
prepare stmt from 'select ? as a';
execute stmt using @a;
end|
set @a=1|
call p1()|
a
1
call p1()|
a
1
drop procedure p1|
drop table if exists t1|
create table t1 (id integer primary key auto_increment,
stmt_text char(35), status varchar(20))|
insert into t1 (stmt_text) values
("select 1"), ("flush tables"), ("handler t1 open as ha"),
("analyze table t1"), ("check table t1"), ("checksum table t1"),
("check table t1"), ("optimize table t1"), ("repair table t1"),
("describe extended select * from t1"),
("help help"), ("show databases"), ("show tables"),
("show table status"), ("show open tables"), ("show storage engines"),
("insert into t1 (id) values (1)"), ("update t1 set status=''"),
("delete from t1"), ("truncate t1"), ("call p1()"), ("foo bar")|
create procedure p1()
begin
declare v_stmt_text varchar(255);
declare v_id integer;
declare done int default 0;
declare c cursor for select id, stmt_text from t1;
declare continue handler for 1295 -- ER_UNSUPPORTED_PS
set @status='not supported';
declare continue handler for 1064 -- ER_SYNTAX_ERROR
set @status='syntax error';
declare continue handler for sqlstate '02000' set done = 1;
prepare update_stmt from "update t1 set status=? where id=?";
open c;
repeat
if not done then
fetch c into v_id, v_stmt_text;
set @id=v_id, @stmt_text=v_stmt_text;
set @status="supported";
prepare stmt from @stmt_text;
execute update_stmt using @status, @id;
end if;
until done end repeat;
deallocate prepare update_stmt;
end|
call p1()|
select * from t1|
id stmt_text status
1 select 1 supported
2 flush tables not supported
3 handler t1 open as ha not supported
4 analyze table t1 not supported
5 check table t1 not supported
6 checksum table t1 not supported
7 check table t1 not supported
8 optimize table t1 not supported
9 repair table t1 not supported
10 describe extended select * from t1 supported
11 help help not supported
12 show databases supported
13 show tables supported
14 show table status supported
15 show open tables supported
16 show storage engines supported
17 insert into t1 (id) values (1) supported
18 update t1 set status='' supported
19 delete from t1 supported
20 truncate t1 supported
21 call p1() supported
22 foo bar syntax error
drop procedure p1|
drop table t1|
prepare stmt from 'select 1'|
create procedure p1() execute stmt|
call p1()|
1
1
call p1()|
1
1
drop procedure p1|
create function f1() returns int
begin
deallocate prepare stmt;
return 1;
end|
ERROR 0A000: Dynamic SQL is not allowed in stored function or trigger
create procedure p1()
begin
prepare stmt from 'select 1 A';
execute stmt;
end|
prepare stmt from 'call p1()'|
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
drop procedure p1|
drop table if exists t1, t2|
create procedure p1 (a int) language sql deterministic
begin
declare rsql varchar(100);
drop table if exists t1, t2;
set @rsql= "create table t1 (a int)";
select @rsql;
prepare pst from @rsql;
execute pst;
set @rsql= null;
set @rsql= "create table t2 (a int)";
select @rsql;
prepare pst from @rsql;
execute pst;
drop table if exists t1, t2;
end|
set @a:=0|
call p1(@a)|
@rsql
create table t1 (a int)
@rsql
create table t2 (a int)
Warnings:
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
select @a|
@a
0
call p1(@a)|
@rsql
create table t1 (a int)
@rsql
create table t2 (a int)
Warnings:
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
select @a|
@a
0
drop procedure if exists p1|

View File

@ -618,7 +618,7 @@ select * from t1|
call bug8408_p()|
val x
select bug8408_f()|
ERROR 0A000: PROCEDURE test.bug8408_p can't return a result set in the given context
ERROR 0A000: Not allowed to return a result set from a function
drop procedure bug8408_p|
drop function bug8408_f|
create function bug8408() returns int
@ -665,20 +665,6 @@ select default(t30.s1) from t30;
end|
drop procedure bug10969|
drop table t1|
prepare stmt from "select 1";
create procedure p() deallocate prepare stmt;
ERROR 0A000: DEALLOCATE is not allowed in stored procedures
create function f() returns int begin deallocate prepare stmt;
ERROR 0A000: DEALLOCATE is not allowed in stored procedures
create procedure p() prepare stmt from "select 1";
ERROR 0A000: PREPARE is not allowed in stored procedures
create function f() returns int begin prepare stmt from "select 1";
ERROR 0A000: PREPARE is not allowed in stored procedures
create procedure p() execute stmt;
ERROR 0A000: EXECUTE is not allowed in stored procedures
create function f() returns int begin execute stmt;
ERROR 0A000: EXECUTE is not allowed in stored procedures
deallocate prepare stmt;
create table t1(f1 int);
create table t2(f1 int);
CREATE PROCEDURE SP001()

View File

@ -689,7 +689,7 @@ call bug11587();
set new.c2= '2004-04-02';
end|
insert into t1 (c1) values (4),(5),(6);
ERROR 0A000: PROCEDURE test.bug11587 can't return a result set in the given context
ERROR 0A000: Not allowed to return a result set from a trigger
select * from t1;
c1 c2
1 NULL

View File

@ -513,6 +513,11 @@ SHOW VARIABLES LIKE 'table_cache';
Variable_name Value
table_cache 1
SET GLOBAL table_cache=DEFAULT;
set character_set_results=NULL;
select ifnull(@@character_set_results,"really null");
ifnull(@@character_set_results,"really null")
really null
set names latin1;
create table t1 (a int);
select a into @x from t1;
Warnings:

View File

@ -875,29 +875,29 @@ create view v1 as select * from t1;
create view v2 as select * from v1;
create view v3 as select v2.col1 from v2,t2 where v2.col1 = t2.col1;
update v2 set col1 = (select max(col1) from v1);
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v2'.
update v2 set col1 = (select max(col1) from t1);
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v2'.
update v2 set col1 = (select max(col1) from v2);
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
update v2,t2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v2'.
update t1,t2 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't1'.
update v1,t2 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v1' for update in FROM clause
update t2,v2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't2'.
update t2,t1 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't2'.
update t2,v1 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't2'.
update v2,t2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v2'.
update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
update v1,t2 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v1' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v1'.
update t2,v2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
update t2,t1 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
@ -907,73 +907,73 @@ ERROR HY000: You can't specify target table 't2' for update in FROM clause
update v2,t2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
update t1,t2 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't1'.
update v1,t2 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v1' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v1'.
update t2,v2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't2'.
update t2,t1 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't2'.
update t2,v1 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 't2'.
update v3 set v3.col1 = (select max(col1) from v1);
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 'v3'.
update v3 set v3.col1 = (select max(col1) from t1);
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v3' prevents operation UPDATE on table 'v3'.
update v3 set v3.col1 = (select max(col1) from v2);
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation UPDATE on table 'v3'.
update v3 set v3.col1 = (select max(col1) from v3);
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
delete from v2 where col1 = (select max(col1) from v1);
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'.
delete from v2 where col1 = (select max(col1) from t1);
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v2'.
delete from v2 where col1 = (select max(col1) from v2);
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v2'.
delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 't1'.
delete v1 from v1,t2 where (select max(col1) from v1) > 0 and v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v1' for update in FROM clause
delete v2 from v2,t2 where (select max(col1) from t1) > 0 and v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v2'.
delete t1 from t1,t2 where (select max(col1) from t1) > 0 and t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
delete v1 from v1,t2 where (select max(col1) from t1) > 0 and v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v1' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation DELETE on table 'v1'.
delete v2 from v2,t2 where (select max(col1) from v2) > 0 and v2.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
delete t1 from t1,t2 where (select max(col1) from v2) > 0 and t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 't1'.
delete v1 from v1,t2 where (select max(col1) from v2) > 0 and v1.col1 = t2.col1;
ERROR HY000: You can't specify target table 'v1' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation DELETE on table 'v1'.
insert into v2 values ((select max(col1) from v1));
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v2'.
insert into t1 values ((select max(col1) from v1));
ERROR HY000: You can't specify target table 't1' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 't1'.
insert into v2 values ((select max(col1) from v1));
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v2'.
insert into v2 values ((select max(col1) from t1));
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v2'.
insert into t1 values ((select max(col1) from t1));
ERROR HY000: You can't specify target table 't1' for update in FROM clause
insert into v2 values ((select max(col1) from t1));
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v2'.
insert into v2 values ((select max(col1) from v2));
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
insert into t1 values ((select max(col1) from v2));
ERROR HY000: You can't specify target table 't1' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 't1'.
insert into v2 values ((select max(col1) from v2));
ERROR HY000: You can't specify target table 'v2' for update in FROM clause
insert into v3 (col1) values ((select max(col1) from v1));
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v1' prevents operation INSERT on table 'v3'.
insert into v3 (col1) values ((select max(col1) from t1));
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v3' prevents operation INSERT on table 'v3'.
insert into v3 (col1) values ((select max(col1) from v2));
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v3'.
insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2));
ERROR HY000: You can't specify target table 'v3' for update in FROM clause
ERROR HY000: The definition of table 'v2' prevents operation INSERT on table 'v3'.
insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2));
insert into mysql.time_zone values ('', (select CONVERT_TZ('20050101000000','UTC','MET') from t2));
ERROR 23000: Column 'Use_leap_seconds' cannot be null
@ -1332,7 +1332,7 @@ insert into v3 values (30);
ERROR HY000: The target table v3 of the INSERT is not updatable
create view v4 as select * from v2 where 20 < (select (s1) from t1);
insert into v4 values (30);
ERROR HY000: You can't specify target table 'v4' for update in FROM clause
ERROR HY000: The target table v4 of the INSERT is not updatable
drop view v4, v3, v2, v1;
drop table t1;
create table t1 (a int);
@ -1935,6 +1935,16 @@ SELECT * FROM v1;
SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1)
dkjhgd
drop view v1;
create table t1 (f59 int, f60 int, f61 int);
insert into t1 values (19,41,32);
create view v1 as select f59, f60 from t1 where f59 in
(select f59 from t1);
update v1 set f60=2345;
ERROR HY000: The target table v1 of the UPDATE is not updatable
update t1 set f60=(select max(f60) from v1);
ERROR HY000: The definition of table 'v1' prevents operation UPDATE on table 't1'.
drop view v1;
drop table t1;
create table t1 (s1 int);
create view v1 as select var_samp(s1) from t1;
show create view v1;

View File

@ -23,29 +23,29 @@ create table t2aA (col1 int);
create view v1Aa as select * from t1aA;
create view v2aA as select * from v1aA;
create view v3Aa as select v2Aa.col1 from v2aA,t2Aa where v2Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update v2aA set col1 = (select max(col1) from v1Aa);
-- error 1093
-- error 1443
update v2Aa set col1 = (select max(col1) from t1Aa);
-- error 1093
update v2aA set col1 = (select max(col1) from v2Aa);
-- error 1093
-- error 1443
update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v1aA) where v2aA.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v1Aa) where t1aA.col1 = t2aA.col1;
-- error 1093
update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from v1aA) where v2Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v1Aa) where t1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t2Aa,v1aA set v1Aa.col1 = (select max(col1) from v1aA) where v1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from t1aA) where v2aA.col1 = t2aA.col1;
-- error 1093
update t1Aa,t2Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 = t2aA.col1;
-- error 1093
-- error 1443
update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from t1Aa) where v1aA.col1 = t2aA.col1;
-- error 1093
update t2Aa,v2Aa set v2aA.col1 = (select max(col1) from t1aA) where v2Aa.col1 = t2aA.col1;
@ -55,71 +55,71 @@ update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from t1Aa) where t1aA.col1 =
update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from t1Aa) where v1Aa.col1 = t2aA.col1;
-- error 1093
update v2aA,t2Aa set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t1aA,t2Aa set t1Aa.col1 = (select max(col1) from v2aA) where t1aA.col1 = t2aA.col1;
-- error 1093
-- error 1443
update v1aA,t2Aa set v1Aa.col1 = (select max(col1) from v2Aa) where v1aA.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t2Aa,v2aA set v2Aa.col1 = (select max(col1) from v2aA) where v2Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t2Aa,t1Aa set t1aA.col1 = (select max(col1) from v2aA) where t1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update t2Aa,v1Aa set v1aA.col1 = (select max(col1) from v2Aa) where v1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
update v3aA set v3Aa.col1 = (select max(col1) from v1aA);
-- error 1093
-- error 1443
update v3aA set v3Aa.col1 = (select max(col1) from t1aA);
-- error 1093
-- error 1443
update v3aA set v3Aa.col1 = (select max(col1) from v2aA);
-- error 1093
update v3aA set v3Aa.col1 = (select max(col1) from v3aA);
-- error 1093
-- error 1443
delete from v2Aa where col1 = (select max(col1) from v1Aa);
-- error 1093
-- error 1443
delete from v2aA where col1 = (select max(col1) from t1Aa);
-- error 1093
delete from v2Aa where col1 = (select max(col1) from v2aA);
-- error 1093
-- error 1443
delete v2Aa from v2aA,t2Aa where (select max(col1) from v1aA) > 0 and v2Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
delete t1aA from t1Aa,t2Aa where (select max(col1) from v1Aa) > 0 and t1aA.col1 = t2aA.col1;
-- error 1093
delete v1aA from v1Aa,t2Aa where (select max(col1) from v1aA) > 0 and v1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
delete v2aA from v2Aa,t2Aa where (select max(col1) from t1Aa) > 0 and v2aA.col1 = t2aA.col1;
-- error 1093
delete t1aA from t1Aa,t2Aa where (select max(col1) from t1aA) > 0 and t1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
delete v1aA from v1Aa,t2Aa where (select max(col1) from t1aA) > 0 and v1aA.col1 = t2aA.col1;
-- error 1093
delete v2Aa from v2aA,t2Aa where (select max(col1) from v2Aa) > 0 and v2aA.col1 = t2aA.col1;
-- error 1093
-- error 1443
delete t1Aa from t1aA,t2Aa where (select max(col1) from v2Aa) > 0 and t1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
delete v1Aa from v1aA,t2Aa where (select max(col1) from v2aA) > 0 and v1Aa.col1 = t2aA.col1;
-- error 1093
-- error 1443
insert into v2Aa values ((select max(col1) from v1aA));
-- error 1093
-- error 1443
insert into t1aA values ((select max(col1) from v1Aa));
-- error 1093
-- error 1443
insert into v2aA values ((select max(col1) from v1aA));
-- error 1093
-- error 1443
insert into v2Aa values ((select max(col1) from t1Aa));
-- error 1093
insert into t1aA values ((select max(col1) from t1Aa));
-- error 1093
-- error 1443
insert into v2aA values ((select max(col1) from t1aA));
-- error 1093
insert into v2Aa values ((select max(col1) from v2aA));
-- error 1093
-- error 1443
insert into t1Aa values ((select max(col1) from v2Aa));
-- error 1093
insert into v2aA values ((select max(col1) from v2Aa));
-- error 1093
-- error 1443
insert into v3Aa (col1) values ((select max(col1) from v1Aa));
-- error 1093
-- error 1443
insert into v3aA (col1) values ((select max(col1) from t1aA));
-- error 1093
-- error 1443
insert into v3Aa (col1) values ((select max(col1) from v2aA));
drop view v3aA,v2Aa,v1aA;
drop table t1Aa,t2Aa;

View File

@ -36,4 +36,22 @@ sync_with_master;
--replace_column 1 # 8 # 9 # 23 # 33 #
show slave status;
#
# BUG#12542
# TEST: "SET ONE_SHOT should always be executed on slave"
#
# We could use any timezone different than server default in this test
#
connection master;
create table t1 (ts timestamp);
set one_shot time_zone='met';
insert into t1 values('2005-08-12 00:00:00');
set one_shot time_zone='met';
select * from t1;
sync_slave_with_master;
connection slave;
set one_shot time_zone='met';
select * from t1;
# End of 4.1 tests

View File

@ -0,0 +1,335 @@
delimiter |;
######################################################################
# Test Dynamic SQL in stored procedures. #############################
######################################################################
#
# A. Basics
#
create procedure p1()
begin
prepare stmt from "select 1";
execute stmt;
execute stmt;
execute stmt;
deallocate prepare stmt;
end|
call p1()|
call p1()|
call p1()|
drop procedure p1|
#
# B. Recursion. Recusion is disabled in SP, and recursive use of PS is not
# possible as well.
#
create procedure p1()
begin
execute stmt;
end|
prepare stmt from "call p1()"|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_SP_NO_RECURSION
call p1()|
--error ER_SP_NO_RECURSION
call p1()|
--error ER_SP_NO_RECURSION
call p1()|
drop procedure p1|
#
# C. Create/drop a stored procedure in Dynamic SQL.
# One cannot create stored procedure from a stored procedure because of
# the way MySQL SP cache works: it's important that this limitation is not
# possible to circumvent by means of Dynamic SQL.
#
create procedure p1()
begin
prepare stmt from "create procedure p2() begin select 1; end";
execute stmt;
deallocate prepare stmt;
end|
--error ER_UNSUPPORTED_PS
call p1()|
--error ER_UNSUPPORTED_PS
call p1()|
drop procedure p1|
create procedure p1()
begin
prepare stmt from "drop procedure p2";
execute stmt;
deallocate prepare stmt;
end|
--error ER_UNSUPPORTED_PS
call p1()|
--error ER_UNSUPPORTED_PS
call p1()|
drop procedure p1|
#
# D. Create/Drop a table (a DDL that issues a commit) in Dynamic SQL.
# (should work ok).
#
create procedure p1()
begin
prepare stmt_drop from "drop table if exists t1";
execute stmt_drop;
prepare stmt from "create table t1 (a int)";
execute stmt;
insert into t1 (a) values (1);
select * from t1;
deallocate prepare stmt;
deallocate prepare stmt_drop;
end|
call p1()|
call p1()|
drop procedure p1|
#
# A more real example (a case similar to submitted by 24/7).
#
create procedure p1()
begin
set @tab_name=concat("tab_", replace(curdate(), '-', '_'));
set @drop_sql=concat("drop table if exists ", @tab_name);
set @create_sql=concat("create table ", @tab_name, " (a int)");
set @insert_sql=concat("insert into ", @tab_name, " values (1), (2), (3)");
set @select_sql=concat("select * from ", @tab_name);
select @tab_name;
select @drop_sql;
select @create_sql;
select @insert_sql;
select @select_sql;
prepare stmt_drop from @drop_sql;
execute stmt_drop;
prepare stmt from @create_sql;
execute stmt;
prepare stmt from @insert_sql;
execute stmt;
prepare stmt from @select_sql;
execute stmt;
execute stmt_drop;
deallocate prepare stmt;
deallocate prepare stmt_drop;
end|
--disable_result_log
call p1()|
call p1()|
--enable_result_log
drop procedure p1|
#
# E. Calling a stored procedure with Dynamic SQL
# from a stored function (currently disabled).
#
create procedure p1()
begin
prepare stmt_drop from "drop table if exists t1";
execute stmt_drop;
prepare stmt from "create table t1 (a int)";
execute stmt;
deallocate prepare stmt;
deallocate prepare stmt_drop;
end|
--disable_warnings
drop function if exists f1|
--enable_warnings
create function f1(a int) returns int
begin
call p1();
return 1;
end|
# Every stored procedure that contains Dynamic SQL is marked as
# such. Stored procedures that contain Dynamic SQL are not
# allowed in a stored function or trigger, and here we get the
# corresponding error message.
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select f1(0)|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select f1(f1(0))|
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
select f1(f1(f1(0)))|
drop function f1|
drop procedure p1|
#
# F. Rollback and cleanup lists management in Dynamic SQL.
#
create procedure p1()
begin
drop table if exists t1;
create table t1 (id integer not null primary key,
name varchar(20) not null);
insert into t1 (id, name) values (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
prepare stmt from "select name from t1";
execute stmt;
select name from t1;
execute stmt;
prepare stmt from
"select name from t1 where name=(select name from t1 where id=2)";
execute stmt;
select name from t1 where name=(select name from t1 where id=2);
execute stmt;
end|
call p1()|
call p1()|
drop procedure p1|
#
# H. Executing a statement prepared externally in SP.
#
prepare stmt from "select * from t1"|
create procedure p1()
begin
execute stmt;
deallocate prepare stmt;
end|
call p1()|
--error ER_UNKNOWN_STMT_HANDLER
call p1()|
drop procedure p1|
#
# I. Use of an SP variable in Dynamic SQL is not possible and
# this limitation is necessary for correct binary logging: prepared
# statements do not substitute SP variables with their values for binlog, so
# SP variables must be not accessible in Dynamic SQL.
#
create procedure p1()
begin
declare a char(10);
set a="sp-variable";
set @a="mysql-variable";
prepare stmt from "select 'dynamic sql:', @a, a";
execute stmt;
end|
--error ER_BAD_FIELD_ERROR
call p1()|
--error ER_BAD_FIELD_ERROR
call p1()|
drop procedure p1|
#
# J. Use of placeholders in Dynamic SQL.
#
create procedure p1()
begin
prepare stmt from 'select ? as a';
execute stmt using @a;
end|
set @a=1|
call p1()|
call p1()|
drop procedure p1|
#
# K. Use of continue handlers with Dynamic SQL.
#
drop table if exists t1|
create table t1 (id integer primary key auto_increment,
stmt_text char(35), status varchar(20))|
insert into t1 (stmt_text) values
("select 1"), ("flush tables"), ("handler t1 open as ha"),
("analyze table t1"), ("check table t1"), ("checksum table t1"),
("check table t1"), ("optimize table t1"), ("repair table t1"),
("describe extended select * from t1"),
("help help"), ("show databases"), ("show tables"),
("show table status"), ("show open tables"), ("show storage engines"),
("insert into t1 (id) values (1)"), ("update t1 set status=''"),
("delete from t1"), ("truncate t1"), ("call p1()"), ("foo bar")|
create procedure p1()
begin
declare v_stmt_text varchar(255);
declare v_id integer;
declare done int default 0;
declare c cursor for select id, stmt_text from t1;
declare continue handler for 1295 -- ER_UNSUPPORTED_PS
set @status='not supported';
declare continue handler for 1064 -- ER_SYNTAX_ERROR
set @status='syntax error';
declare continue handler for sqlstate '02000' set done = 1;
prepare update_stmt from "update t1 set status=? where id=?";
open c;
repeat
if not done then
fetch c into v_id, v_stmt_text;
set @id=v_id, @stmt_text=v_stmt_text;
set @status="supported";
prepare stmt from @stmt_text;
execute update_stmt using @status, @id;
end if;
until done end repeat;
deallocate prepare update_stmt;
end|
call p1()|
select * from t1|
drop procedure p1|
drop table t1|
#
# Bug#7115 "Prepared Statements: packet error if execution within stored
# procedure".
#
prepare stmt from 'select 1'|
create procedure p1() execute stmt|
call p1()|
call p1()|
drop procedure p1|
#
# Bug#10975 "Prepared statements: crash if function deallocates"
# Check that a prepared statement that is currently in use
# can't be deallocated.
#
# a) Prepared statements and stored procedure cache:
#
# TODO: add when the corresponding bug (Bug #12093 "SP not found on second
# PS execution if another thread drops other SP in between") is fixed.
#
# b) attempt to deallocate a prepared statement that is being executed
--error ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG
create function f1() returns int
begin
deallocate prepare stmt;
return 1;
end|
# b)-2 a crash (#1) spotted by Sergey Petrunia during code review
create procedure p1()
begin
prepare stmt from 'select 1 A';
execute stmt;
end|
prepare stmt from 'call p1()'|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
drop procedure p1|
#
# Bug#10605 "Stored procedure with multiple SQL prepared statements
# disconnects client"
#
--disable_warnings
drop table if exists t1, t2|
--enable_warnings
create procedure p1 (a int) language sql deterministic
begin
declare rsql varchar(100);
drop table if exists t1, t2;
set @rsql= "create table t1 (a int)";
select @rsql;
prepare pst from @rsql;
execute pst;
set @rsql= null;
set @rsql= "create table t2 (a int)";
select @rsql;
prepare pst from @rsql;
execute pst;
drop table if exists t1, t2;
end|
set @a:=0|
call p1(@a)|
select @a|
call p1(@a)|
select @a|
drop procedure if exists p1|
# End of the test
delimiter ;|

View File

@ -875,7 +875,7 @@ create procedure bug8408_p()
select * from t1|
call bug8408_p()|
--error ER_SP_BADSELECT
--error ER_SP_NO_RETSET
select bug8408_f()|
drop procedure bug8408_p|
@ -956,39 +956,10 @@ end|
drop procedure bug10969|
#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
#drop procedure if exists bugNNNN|
#--enable_warnings
#create procedure bugNNNN...
drop table t1|
delimiter ;|
#
# Bug#10975, #10605, #7115: Dynamic SQL by means of
# PREPARE/EXECUTE/DEALLOCATE is not supported yet.
# Check that an error message is returned.
#
prepare stmt from "select 1";
--error ER_SP_BADSTATEMENT
create procedure p() deallocate prepare stmt;
--error ER_SP_BADSTATEMENT
create function f() returns int begin deallocate prepare stmt;
--error ER_SP_BADSTATEMENT
create procedure p() prepare stmt from "select 1";
--error ER_SP_BADSTATEMENT
create function f() returns int begin prepare stmt from "select 1";
--error ER_SP_BADSTATEMENT
create procedure p() execute stmt;
--error ER_SP_BADSTATEMENT
create function f() returns int begin execute stmt;
deallocate prepare stmt;
# BUG#9814: Closing a cursor that is not open
create table t1(f1 int);
create table t2(f1 int);
@ -1114,3 +1085,12 @@ drop function bug11834_1;
execute stmt;
deallocate prepare stmt;
drop function bug11834_2;
#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
#drop procedure if exists bugNNNN|
#--enable_warnings
#create procedure bugNNNN...

View File

@ -723,7 +723,7 @@ begin
end|
delimiter ;|
--error 1312
--error ER_SP_NO_RETSET
insert into t1 (c1) values (4),(5),(6);
select * from t1;

View File

@ -390,6 +390,14 @@ SET GLOBAL table_cache=-1;
SHOW VARIABLES LIKE 'table_cache';
SET GLOBAL table_cache=DEFAULT;
#
# Bugs12363: character_set_results is nullable,
# but value_ptr returns string "NULL"
#
set character_set_results=NULL;
select ifnull(@@character_set_results,"really null");
set names latin1;
# End of 4.1 tests
#

View File

@ -827,29 +827,29 @@ create table t2 (col1 int);
create view v1 as select * from t1;
create view v2 as select * from v1;
create view v3 as select v2.col1 from v2,t2 where v2.col1 = t2.col1;
-- error 1093
-- error 1443
update v2 set col1 = (select max(col1) from v1);
-- error 1093
-- error 1443
update v2 set col1 = (select max(col1) from t1);
-- error 1093
update v2 set col1 = (select max(col1) from v2);
-- error 1093
-- error 1443
update v2,t2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
-- error 1093
-- error 1443
update t1,t2 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
-- error 1093
update v1,t2 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
-- error 1093
-- error 1443
update t2,v2 set v2.col1 = (select max(col1) from v1) where v2.col1 = t2.col1;
-- error 1093
-- error 1443
update t2,t1 set t1.col1 = (select max(col1) from v1) where t1.col1 = t2.col1;
-- error 1093
-- error 1443
update t2,v1 set v1.col1 = (select max(col1) from v1) where v1.col1 = t2.col1;
-- error 1093
-- error 1443
update v2,t2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
-- error 1093
update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
-- error 1093
-- error 1443
update v1,t2 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
-- error 1093
update t2,v2 set v2.col1 = (select max(col1) from t1) where v2.col1 = t2.col1;
@ -859,74 +859,74 @@ update t2,t1 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
update t2,v1 set v1.col1 = (select max(col1) from t1) where v1.col1 = t2.col1;
-- error 1093
update v2,t2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
-- error 1093
-- error 1443
update t1,t2 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
-- error 1093
-- error 1443
update v1,t2 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
-- error 1093
-- error 1443
update t2,v2 set v2.col1 = (select max(col1) from v2) where v2.col1 = t2.col1;
-- error 1093
-- error 1443
update t2,t1 set t1.col1 = (select max(col1) from v2) where t1.col1 = t2.col1;
-- error 1093
-- error 1443
update t2,v1 set v1.col1 = (select max(col1) from v2) where v1.col1 = t2.col1;
-- error 1093
-- error 1443
update v3 set v3.col1 = (select max(col1) from v1);
-- error 1093
-- error 1443
update v3 set v3.col1 = (select max(col1) from t1);
-- error 1093
-- error 1443
update v3 set v3.col1 = (select max(col1) from v2);
-- error 1093
update v3 set v3.col1 = (select max(col1) from v3);
-- error 1093
-- error 1443
delete from v2 where col1 = (select max(col1) from v1);
-- error 1093
-- error 1443
delete from v2 where col1 = (select max(col1) from t1);
-- error 1093
delete from v2 where col1 = (select max(col1) from v2);
-- error 1093
-- error 1443
delete v2 from v2,t2 where (select max(col1) from v1) > 0 and v2.col1 = t2.col1;
-- error 1093
-- error 1443
delete t1 from t1,t2 where (select max(col1) from v1) > 0 and t1.col1 = t2.col1;
-- error 1093
delete v1 from v1,t2 where (select max(col1) from v1) > 0 and v1.col1 = t2.col1;
-- error 1093
-- error 1443
delete v2 from v2,t2 where (select max(col1) from t1) > 0 and v2.col1 = t2.col1;
-- error 1093
delete t1 from t1,t2 where (select max(col1) from t1) > 0 and t1.col1 = t2.col1;
-- error 1093
-- error 1443
delete v1 from v1,t2 where (select max(col1) from t1) > 0 and v1.col1 = t2.col1;
-- error 1093
delete v2 from v2,t2 where (select max(col1) from v2) > 0 and v2.col1 = t2.col1;
-- error 1093
-- error 1443
delete t1 from t1,t2 where (select max(col1) from v2) > 0 and t1.col1 = t2.col1;
-- error 1093
-- error 1443
delete v1 from v1,t2 where (select max(col1) from v2) > 0 and v1.col1 = t2.col1;
-- error 1093
-- error 1443
insert into v2 values ((select max(col1) from v1));
-- error 1093
-- error 1443
insert into t1 values ((select max(col1) from v1));
-- error 1093
-- error 1443
insert into v2 values ((select max(col1) from v1));
-- error 1093
-- error 1443
insert into v2 values ((select max(col1) from t1));
-- error 1093
insert into t1 values ((select max(col1) from t1));
-- error 1093
-- error 1443
insert into v2 values ((select max(col1) from t1));
-- error 1093
insert into v2 values ((select max(col1) from v2));
-- error 1093
-- error 1443
insert into t1 values ((select max(col1) from v2));
-- error 1093
insert into v2 values ((select max(col1) from v2));
-- error 1093
-- error 1443
insert into v3 (col1) values ((select max(col1) from v1));
-- error 1093
-- error 1443
insert into v3 (col1) values ((select max(col1) from t1));
-- error 1093
-- error 1443
insert into v3 (col1) values ((select max(col1) from v2));
#check with TZ tables in list
-- error 1093
-- error 1443
insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from v2));
insert into v3 (col1) values ((select CONVERT_TZ('20050101000000','UTC','MET') from t2));
-- error 1048
@ -1242,7 +1242,7 @@ create view v3 as select * from t1 where 20 < (select (s1) from v2);
-- error 1288
insert into v3 values (30);
create view v4 as select * from v2 where 20 < (select (s1) from t1);
-- error 1093
-- error 1288
insert into v4 values (30);
drop view v4, v3, v2, v1;
drop table t1;
@ -1760,6 +1760,20 @@ CREATE VIEW v1 AS SELECT SUBSTRING_INDEX("dkjhgd:kjhdjh", ":", 1);
SELECT * FROM v1;
drop view v1;
#
# hide underlying tables names in case of imposibility to update (BUG#10773)
#
create table t1 (f59 int, f60 int, f61 int);
insert into t1 values (19,41,32);
create view v1 as select f59, f60 from t1 where f59 in
(select f59 from t1);
-- error 1288
update v1 set f60=2345;
-- error 1443
update t1 set f60=(select max(f60) from v1);
drop view v1;
drop table t1;
#
# Using var_samp with view (BUG#10651)
#

View File

@ -412,7 +412,12 @@ sub get_mysqladmin_options
$mysqladmin_found= 0 if (!length($mysqladmin));
$com = "$mysqladmin";
$tmp = " -u $opt_user";
$tmp.= defined($opt_password) ? " -p$opt_password" : "";
if (defined($opt_password)) {
my $pw= $opt_password;
# Protect single quotes in password
$pw =~ s/'/'"'"'/g;
$tmp.= " -p'$pw'";
}
$tmp.= $opt_tcp_ip ? " -h 127.0.0.1" : "";
for ($j = 0; defined($options[$j]); $j++)
{

View File

@ -2760,6 +2760,9 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg)
case MYSQL_REPORT_DATA_TRUNCATION:
mysql->options.report_data_truncation= test(*(my_bool *) arg);
break;
case MYSQL_OPT_RECONNECT:
mysql->reconnect= *(my_bool *) arg;
break;
default:
DBUG_RETURN(1);
}

View File

@ -282,6 +282,7 @@ public:
HA_CREATE_INFO *create_info); //required
ha_rows records_in_range(uint inx, key_range *start_key,
key_range *end_key);
uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type); //required

View File

@ -463,13 +463,9 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
/* Since we rolled back the whole transaction, we must
tell it also to MySQL so that MySQL knows to empty the
cached binlog for this transaction */
if (thd) {
ha_rollback(thd);
}
/* Starting from 5.0.13, we let MySQL just roll back the
latest SQL statement in a lock wait timeout. Previously, we
rolled back the whole transaction. */
return(HA_ERR_LOCK_WAIT_TIMEOUT);
@ -5539,6 +5535,33 @@ ha_innobase::info(
trx_get_error_info(prebuilt->trx));
}
if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
longlong auto_inc;
int ret;
/* The following function call can the first time fail in
a lock wait timeout error because it reserves the auto-inc
lock on the table. If it fails, then someone is already initing
the auto-inc counter, and the second call is guaranteed to
succeed. */
ret = innobase_read_and_init_auto_inc(&auto_inc);
if (ret != 0) {
ret = innobase_read_and_init_auto_inc(&auto_inc);
if (ret != 0) {
ut_print_timestamp(stderr);
sql_print_error("Cannot get table %s auto-inc"
"counter value in ::info\n",
ib_table->name);
auto_inc = 0;
}
}
auto_increment_value = auto_inc;
}
prebuilt->trx->op_info = (char*)"";
DBUG_VOID_RETURN;
@ -6847,8 +6870,13 @@ ha_innobase::innobase_read_and_init_auto_inc(
goto func_exit;
}
} else {
/* Initialize to max(col) + 1 */
auto_inc = (longlong) table->next_number_field->
/* Initialize to max(col) + 1; we use
'found_next_number_field' below because MySQL in SHOW TABLE
STATUS does not seem to set 'next_number_field'. The comment
in table.h says that 'next_number_field' is set when it is
'active'. */
auto_inc = (longlong) table->found_next_number_field->
val_int_offset(table->s->rec_buff_length) + 1;
}
@ -6863,9 +6891,11 @@ func_exit:
func_exit_early:
/* Since MySQL does not seem to call autocommit after SHOW TABLE
STATUS (even if we would register the trx here), we must commit our
STATUS (even if we would register the trx here), we commit our
transaction here if it was started here. This is to eliminate a
dangling transaction. */
dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
TABLE STATUS does leave a dangling transaction if the user does not
himself call COMMIT. */
if (trx_was_not_started) {

View File

@ -1296,7 +1296,7 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
In case we're in statement prepare, create conversion item
in its memory: it will be reused on each execute.
*/
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
for (arg= args, last= args + nargs; arg < last; arg++)
{
@ -1342,7 +1342,7 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
conv->fix_fields(thd, arg);
}
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
return res;
}
@ -1385,7 +1385,7 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
structure can go away and pop up again between subsequent executions
of a prepared statement).
*/
if (thd->current_arena->is_stmt_prepare_or_first_sp_execute())
if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
{
if (db_name)
orig_db_name= thd->strdup(db_name);
@ -4985,10 +4985,7 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
{
if (context->error_processor == &view_error_processor)
{
TABLE_LIST *view= (cached_table->belong_to_view ?
cached_table->belong_to_view :
cached_table);
// TODO: make correct error message
TABLE_LIST *view= cached_table->top_table();
push_warning_printf(field_arg->table->in_use,
MYSQL_ERROR::WARN_LEVEL_WARN,
ER_NO_DEFAULT_FOR_VIEW_FIELD,

View File

@ -671,7 +671,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
If it is preparation PS only then we do not know values of parameters =>
cant't get there values and do not need that values.
*/
if (!thd->current_arena->is_stmt_prepare())
if (!thd->stmt_arena->is_stmt_prepare())
cache->store(args[0]);
if (cache->cols() == 1)
{

View File

@ -1875,7 +1875,7 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref)
if (arg_count)
{ // Only use argument once in query
/*
Allocate rand structure once: we must use thd->current_arena
Allocate rand structure once: we must use thd->stmt_arena
to create rand in proper mem_root if it's a prepared statement or
stored procedure.
@ -1883,7 +1883,7 @@ bool Item_func_rand::fix_fields(THD *thd,Item **ref)
as it will be replicated in the query as such.
*/
if (!rand && !(rand= (struct rand_struct*)
thd->current_arena->alloc(sizeof(*rand))))
thd->stmt_arena->alloc(sizeof(*rand))))
return TRUE;
/*
PARAM_ITEM is returned if we're in statement prepare and consequently
@ -3834,21 +3834,21 @@ longlong Item_func_get_user_var::val_int()
stores this variable and its value in thd->user_var_events, so that it can be
written to the binlog (will be written just before the query is written, see
log.cc).
RETURN
0 OK
0 OK
1 Failed to put appropriate record into binary log
*/
int get_var_with_binlog(THD *thd, LEX_STRING &name,
user_var_entry **out_entry)
int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
LEX_STRING &name, user_var_entry **out_entry)
{
BINLOG_USER_VAR_EVENT *user_var_event;
user_var_entry *var_entry;
var_entry= get_variable(&thd->user_vars, name, 0);
if (!(opt_bin_log && is_update_query(thd->lex->sql_command)))
if (!(opt_bin_log && is_update_query(sql_command)))
{
*out_entry= var_entry;
return 0;
@ -3941,7 +3941,7 @@ void Item_func_get_user_var::fix_length_and_dec()
decimals=NOT_FIXED_DEC;
max_length=MAX_BLOB_WIDTH;
error= get_var_with_binlog(thd, name, &var_entry);
error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
if (var_entry)
{

View File

@ -333,7 +333,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
return RES_OK;
SELECT_LEX *select_lex= join->select_lex;
Query_arena *arena= thd->current_arena;
Query_arena *arena= thd->stmt_arena;
if (!select_lex->master_unit()->first_select()->next_select() &&
!select_lex->table_list.elements &&
@ -1287,10 +1287,10 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
*/
if (!optimizer)
{
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
if (result)
goto err;
}
@ -1306,7 +1306,7 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
goto err;
transformed= 1;
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
/*
Both transformers call fix_fields() only for Items created inside them,
and all that items do not make permanent changes in current item arena
@ -1322,14 +1322,14 @@ Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
if (func != &eq_creator)
{
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
DBUG_RETURN(RES_ERROR);
}
res= row_value_transformer(join);
}
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
err:
thd->where= save_where;
DBUG_RETURN(res);

View File

@ -26,7 +26,6 @@ class JOIN;
class select_subselect;
class subselect_engine;
class Item_bool_func2;
class Item_arena;
/* base class for subselects */

View File

@ -23,8 +23,6 @@
#include <my_tree.h>
class Item_arena;
class Item_sum :public Item_result_field
{
public:

View File

@ -1555,6 +1555,16 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, const char *query
clear_all_errors(thd, rli);
/*
Note: We do not need to execute reset_one_shot_variables() if this
db_ok() test fails.
Reason: The db stored in binlog events is the same for SET and for
its companion query. If the SET is ignored because of
db_ok(), the companion query will also be ignored, and if
the companion query is ignored in the db_ok() test of
::exec_event(), then the companion SET also have so we
don't need to reset_one_shot_variables().
*/
if (rpl_filter->db_ok(thd->db))
{
thd->set_time((time_t)when);
@ -2704,6 +2714,16 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
Create_file_log_event::exec_event() and then discarding Append_block and
al. Another way is do the filtering in the I/O thread (more efficient: no
disk writes at all).
Note: We do not need to execute reset_one_shot_variables() if this
db_ok() test fails.
Reason: The db stored in binlog events is the same for SET and for
its companion query. If the SET is ignored because of
db_ok(), the companion query will also be ignored, and if
the companion query is ignored in the db_ok() test of
::exec_event(), then the companion SET also have so we
don't need to reset_one_shot_variables().
*/
if (rpl_filter->db_ok(thd->db))
{

View File

@ -1177,9 +1177,6 @@ class Xid_log_event: public Log_event
Every time a query uses the value of a user variable, a User_var_log_event is
written before the Query_log_event, to set the user variable.
Every time a query uses the value of a user variable, a User_var_log_event is
written before the Query_log_event, to set the user variable.
****************************************************************************/
class User_var_log_event: public Log_event

View File

@ -415,7 +415,6 @@ enum enum_parsing_place
struct st_table;
class THD;
class Item_arena;
/* Struct to handle simple linked lists */
@ -597,7 +596,7 @@ bool mysql_change_db(THD *thd,const char *name,bool no_access_check);
void mysql_parse(THD *thd,char *inBuf,uint length);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command);
bool alloc_query(THD *thd, char *packet, ulong packet_length);
bool alloc_query(THD *thd, const char *packet, uint packet_length);
void mysql_init_select(LEX *lex);
void mysql_reset_thd_for_next_command(THD *thd);
void mysql_init_query(THD *thd, uchar *buf, uint length);
@ -876,16 +875,17 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
bool get_schema_tables_result(JOIN *join);
/* sql_prepare.cc */
bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
LEX_STRING *name);
void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length);
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name);
void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length);
void mysql_stmt_close(THD *thd, char *packet);
void mysql_sql_stmt_prepare(THD *thd);
void mysql_sql_stmt_execute(THD *thd);
void mysql_sql_stmt_close(THD *thd);
void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length);
void mysql_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
void reinit_stmt_before_use(THD *thd, LEX *lex);
void init_stmt_after_parse(THD*, LEX*);
/* sql_handler.cc */
bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen);
@ -924,6 +924,9 @@ void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item);
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
void update_non_unique_table_error(TABLE_LIST *update,
const char *operation,
TABLE_LIST *duplicate);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds,
@ -1390,8 +1393,8 @@ extern int sql_cache_hit(THD *thd, char *inBuf, uint length);
/* item_func.cc */
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
LEX_STRING component);
int get_var_with_binlog(THD *thd, LEX_STRING &name,
user_var_entry **out_entry);
int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
LEX_STRING &name, user_var_entry **out_entry);
/* log.cc */
bool flush_error_log(void);

View File

@ -1730,11 +1730,17 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
return new Item_int((int32) *(my_bool*) value_ptr(thd, var_type, base),1);
case SHOW_CHAR:
{
Item_string *tmp;
Item *tmp;
pthread_mutex_lock(&LOCK_global_system_variables);
char *str= (char*) value_ptr(thd, var_type, base);
tmp= new Item_string(str, strlen(str),
system_charset_info, DERIVATION_SYSCONST);
if (str)
tmp= new Item_string(str, strlen(str),
system_charset_info, DERIVATION_SYSCONST);
else
{
tmp= new Item_null();
tmp->collation.set(system_charset_info, DERIVATION_SYSCONST);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
return tmp;
}
@ -2024,7 +2030,7 @@ byte *sys_var_character_set::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
CHARSET_INFO *cs= ci_ptr(thd,type)[0];
return cs ? (byte*) cs->csname : (byte*) "NULL";
return cs ? (byte*) cs->csname : (byte*) NULL;
}

View File

@ -5399,6 +5399,10 @@ ER_DATETIME_FUNCTION_OVERFLOW 22008
eng "Datetime function: %-.32s field overflow"
ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
ER_VIEW_PREVENT_UPDATE
eng "The definition of table '%-.64s' prevents operation %s on table '%-.64s'."
ER_PS_NO_RECURSION
eng "The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner"
ER_PARTITION_REQUIRES_VALUES_ERROR
eng "%s PARTITIONING requires definition of VALUES %s for each partition"
swe "%s PARTITIONering kräver definition av VALUES %s för varje partition"

View File

@ -1338,7 +1338,7 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, HASH *src)
for (uint i=0 ; i < src->records ; i++)
{
Sroutine_hash_entry *rt= (Sroutine_hash_entry *)hash_element(src, i);
(void)add_used_routine(lex, thd->current_arena, &rt->key);
(void)add_used_routine(lex, thd->stmt_arena, &rt->key);
}
}
@ -1485,7 +1485,7 @@ void
sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers)
{
if (add_used_routine(lex, thd->current_arena, &triggers->sroutines_key))
if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key))
{
Sroutine_hash_entry **last_cached_routine_ptr=
(Sroutine_hash_entry **)lex->sroutines_list.next;

View File

@ -47,15 +47,30 @@ sp_map_result_type(enum enum_field_types type)
}
/*
* Returns TRUE if the 'cmd' is a command that might result in
* multiple result sets being sent back.
* Note: This does not include SQLCOM_SELECT which is treated
* separately in sql_yacc.yy.
*/
bool
sp_multi_results_command(enum enum_sql_command cmd)
SYNOPSIS
sp_get_flags_for_command()
DESCRIPTION
Returns a combination of:
* sp_head::MULTI_RESULTS: added if the 'cmd' is a command that might
result in multiple result sets being sent back.
* sp_head::CONTAINS_DYNAMIC_SQL: added if 'cmd' is one of PREPARE,
EXECUTE, DEALLOCATE.
*/
uint
sp_get_flags_for_command(LEX *lex)
{
switch (cmd) {
uint flags;
switch (lex->sql_command) {
case SQLCOM_SELECT:
if (lex->result)
{
flags= 0; /* This is a SELECT with INTO clause */
break;
}
/* fallthrough */
case SQLCOM_ANALYZE:
case SQLCOM_CHECKSUM:
case SQLCOM_HA_READ:
@ -90,10 +105,26 @@ sp_multi_results_command(enum enum_sql_command cmd)
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_WARNS:
return TRUE;
flags= sp_head::MULTI_RESULTS;
break;
/*
EXECUTE statement may return a result set, but doesn't have to.
We can't, however, know it in advance, and therefore must add
this statement here. This is ok, as is equivalent to a result-set
statement within an IF condition.
*/
case SQLCOM_EXECUTE:
flags= sp_head::MULTI_RESULTS | sp_head::CONTAINS_DYNAMIC_SQL;
break;
case SQLCOM_PREPARE:
case SQLCOM_DEALLOCATE_PREPARE:
flags= sp_head::CONTAINS_DYNAMIC_SQL;
break;
default:
return FALSE;
flags= 0;
break;
}
return flags;
}
@ -131,12 +162,12 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
do \
{ \
if (condition) \
thd->set_n_backup_item_arena(thd->spcont->callers_arena, \
backup_arena); \
thd->set_n_backup_active_arena(thd->spcont->callers_arena, \
backup_arena); \
new_command; \
if (condition) \
thd->restore_backup_item_arena(thd->spcont->callers_arena, \
&backup_current_arena); \
thd->restore_active_arena(thd->spcont->callers_arena, \
backup_arena); \
} while(0)
/*
@ -167,7 +198,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
DBUG_ENTER("sp_eval_func_item");
Item *it= sp_prepare_func_item(thd, it_addr);
uint rsize;
Query_arena backup_current_arena;
Query_arena backup_arena;
DBUG_PRINT("info", ("type: %d", type));
if (!it)
@ -187,7 +218,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
}
DBUG_PRINT("info", ("INT_RESULT: %d", i));
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_int(i),
use_callers_arena, &backup_current_arena);
use_callers_arena, &backup_arena);
break;
}
case REAL_RESULT:
@ -210,7 +241,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
max_length= it->max_length;
DBUG_PRINT("info", ("REAL_RESULT: %g", d));
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_float(d),
use_callers_arena, &backup_current_arena);
use_callers_arena, &backup_arena);
it->decimals= decimals;
it->max_length= max_length;
break;
@ -221,7 +252,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
if (it->null_value)
goto return_null_item;
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_decimal(val),
use_callers_arena, &backup_current_arena);
use_callers_arena, &backup_arena);
#ifndef DBUG_OFF
{
char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
@ -246,7 +277,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
s->length(), s->c_ptr_quick()));
CHARSET_INFO *itcs= it->collation.collation;
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_string(itcs),
use_callers_arena, &backup_current_arena);
use_callers_arena, &backup_arena);
/*
We have to use special constructor and allocate string
on system heap here. This is because usual Item_string
@ -276,7 +307,7 @@ sp_eval_func_item(THD *thd, Item **it_addr, enum enum_field_types type,
return_null_item:
CREATE_ON_CALLERS_ARENA(it= new(reuse, &rsize) Item_null(),
use_callers_arena, &backup_current_arena);
use_callers_arena, &backup_arena);
it->rsize= rsize;
DBUG_RETURN(it);
@ -364,9 +395,7 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
m_returns_cs(NULL), m_has_return(FALSE),
m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE),
m_is_invoked(FALSE)
m_flags(0), m_returns_cs(NULL)
{
extern byte *
sp_table_key(const byte *ptr, uint *plen, my_bool first);
@ -765,7 +794,7 @@ int sp_head::execute(THD *thd)
/* per-instruction arena */
MEM_ROOT execute_mem_root;
Query_arena execute_arena(&execute_mem_root, INITIALIZED_FOR_SP),
execute_backup_arena;
backup_arena;
query_id_t old_query_id;
TABLE *old_derived_tables;
LEX *old_lex;
@ -782,7 +811,7 @@ int sp_head::execute(THD *thd)
DBUG_RETURN(-1);
}
if (m_is_invoked)
if (m_flags & IS_INVOKED)
{
/*
We have to disable recursion for stored routines since in
@ -802,7 +831,7 @@ int sp_head::execute(THD *thd)
my_error(ER_SP_NO_RECURSION, MYF(0));
DBUG_RETURN(-1);
}
m_is_invoked= TRUE;
m_flags|= IS_INVOKED;
dbchanged= FALSE;
if (m_db.length &&
@ -812,7 +841,7 @@ int sp_head::execute(THD *thd)
if ((ctx= thd->spcont))
ctx->clear_handler();
thd->query_error= 0;
old_arena= thd->current_arena;
old_arena= thd->stmt_arena;
/*
We have to save/restore this info when we are changing call level to
@ -848,13 +877,13 @@ int sp_head::execute(THD *thd)
Switch to per-instruction arena here. We can do it since we cleanup
arena after every instruction.
*/
thd->set_n_backup_item_arena(&execute_arena, &execute_backup_arena);
thd->set_n_backup_active_arena(&execute_arena, &backup_arena);
/*
Save callers arena in order to store instruction results and out
parameters in it later during sp_eval_func_item()
*/
thd->spcont->callers_arena= &execute_backup_arena;
thd->spcont->callers_arena= &backup_arena;
do
{
@ -869,12 +898,12 @@ int sp_head::execute(THD *thd)
if (!thd->in_sub_stmt)
thd->set_time(); // Make current_time() et al work
/*
We have to set thd->current_arena before executing the instruction
We have to set thd->stmt_arena before executing the instruction
to store in the instruction free_list all new items, created
during the first execution (for example expanding of '*' or the
items made during other permanent subquery transformations).
*/
thd->current_arena= i;
thd->stmt_arena= i;
ret= i->execute(thd, &ip);
/*
@ -889,6 +918,15 @@ int sp_head::execute(THD *thd)
/* we should cleanup free_list and memroot, used by instruction */
thd->free_items();
/*
FIXME: we must free user var events only if the routine is executed
in non-prelocked mode and statement-by-statement replication is used.
But if we don't free them now, the server crashes because user var
events are allocated in execute_mem_root. This is Bug#12637, and when
it's fixed, please add if (thd->options & OPTION_BIN_LOG) here.
*/
if (opt_bin_log)
reset_dynamic(&thd->user_var_events);
free_root(&execute_mem_root, MYF(0));
/*
@ -907,9 +945,9 @@ int sp_head::execute(THD *thd)
case SP_HANDLER_NONE:
break;
case SP_HANDLER_CONTINUE:
thd->restore_backup_item_arena(&execute_arena, &execute_backup_arena);
thd->restore_active_arena(&execute_arena, &backup_arena);
ctx->save_variables(hf);
thd->set_n_backup_item_arena(&execute_arena, &execute_backup_arena);
thd->set_n_backup_active_arena(&execute_arena, &backup_arena);
ctx->push_hstack(ip);
// Fall through
default:
@ -924,7 +962,7 @@ int sp_head::execute(THD *thd)
}
} while (ret == 0 && !thd->killed);
thd->restore_backup_item_arena(&execute_arena, &execute_backup_arena);
thd->restore_active_arena(&execute_arena, &backup_arena);
/* Restore all saved */
@ -939,7 +977,7 @@ int sp_head::execute(THD *thd)
thd->derived_tables= old_derived_tables;
thd->variables.sql_mode= save_sql_mode;
thd->current_arena= old_arena;
thd->stmt_arena= old_arena;
state= EXECUTED;
done:
@ -955,7 +993,7 @@ int sp_head::execute(THD *thd)
if (! thd->killed)
ret= mysql_change_db(thd, olddb, 0);
}
m_is_invoked= FALSE;
m_flags&= ~IS_INVOKED;
DBUG_RETURN(ret);
}
@ -1172,7 +1210,7 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont= save_spcont;
DBUG_RETURN(-1);
}
if (csize > 0 || hmax > 0 || cmax > 0)
{
Item_null *nit= NULL; // Re-use this, and only create if needed
@ -1349,7 +1387,7 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
nctx->pop_all_cursors(); // To avoid memory leaks after an error
delete nctx; // Does nothing
thd->spcont= save_spcont;
DBUG_RETURN(ret);
}
@ -1397,7 +1435,6 @@ sp_head::restore_lex(THD *thd)
LEX *sublex= thd->lex;
LEX *oldlex= (LEX *)m_lex.pop();
init_stmt_after_parse(thd, sublex);
if (! oldlex)
return; // Nothing to restore
@ -1532,7 +1569,7 @@ sp_head::restore_thd_mem_root(THD *thd)
{
DBUG_ENTER("sp_head::restore_thd_mem_root");
Item *flist= free_list; // The old list
set_item_arena(thd); // Get new free_list and mem_root
set_query_arena(thd); // Get new free_list and mem_root
state= INITIALIZED_FOR_SP;
DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
@ -2359,20 +2396,18 @@ sp_instr_hreturn::opt_mark(sp_head *sp)
int
sp_instr_cpush::execute(THD *thd, uint *nextp)
{
Query_arena backup_current_arena;
Query_arena backup_arena;
DBUG_ENTER("sp_instr_cpush::execute");
/*
We should create cursors in the callers arena, as
it could be (and usually is) used in several instructions.
*/
thd->set_n_backup_item_arena(thd->spcont->callers_arena,
&backup_current_arena);
thd->set_n_backup_active_arena(thd->spcont->callers_arena, &backup_arena);
thd->spcont->push_cursor(&m_lex_keeper, this);
thd->restore_backup_item_arena(thd->spcont->callers_arena,
&backup_current_arena);
thd->restore_active_arena(thd->spcont->callers_arena, &backup_arena);
*nextp= m_ip+1;
@ -2439,19 +2474,19 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
}
else
{
Query_arena *old_arena= thd->current_arena;
Query_arena *old_arena= thd->stmt_arena;
/*
Get the Query_arena from the cpush instruction, which contains
the free_list of the query, so new items (if any) are stored in
the right free_list, and we can cleanup after each open.
*/
thd->current_arena= c->get_instr();
thd->stmt_arena= c->get_instr();
res= lex_keeper->reset_lex_and_exec_core(thd, nextp, FALSE, this);
/* Cleanup the query's items */
if (thd->current_arena->free_list)
cleanup_items(thd->current_arena->free_list);
thd->current_arena= old_arena;
if (thd->stmt_arena->free_list)
cleanup_items(thd->stmt_arena->free_list);
thd->stmt_arena= old_arena;
/*
Work around the fact that errors in selects are not returned properly
(but instead converted into a warning), so if a condition handler
@ -2526,18 +2561,16 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
{
sp_cursor *c= thd->spcont->get_cursor(m_cursor);
int res;
Query_arena backup_current_arena;
Query_arena backup_arena;
DBUG_ENTER("sp_instr_cfetch::execute");
if (! c)
res= -1;
else
{
thd->set_n_backup_item_arena(thd->spcont->callers_arena,
&backup_current_arena);
thd->set_n_backup_active_arena(thd->spcont->callers_arena, &backup_arena);
res= c->fetch(thd, &m_varlist);
thd->restore_backup_item_arena(thd->spcont->callers_arena,
&backup_current_arena);
thd->restore_active_arena(thd->spcont->callers_arena, &backup_arena);
}
*nextp= m_ip+1;
@ -2790,7 +2823,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
/*
Use persistent arena for table list allocation to be PS friendly.
*/
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
for (i=0 ; i < m_sptabs.records ; i++)
{
@ -2835,7 +2868,7 @@ sp_head::add_used_tables_to_table_list(THD *thd,
}
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(result);
}

View File

@ -33,8 +33,8 @@
Item_result
sp_map_result_type(enum enum_field_types type);
bool
sp_multi_results_command(enum enum_sql_command cmd);
uint
sp_get_flags_for_command(LEX *lex);
struct sp_label;
class sp_instr;
@ -107,18 +107,23 @@ class sp_head :private Query_arena
MEM_ROOT main_mem_root;
public:
/* Possible values of m_flags */
const static int
HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN
IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE
IN_HANDLER= 4, // Is set if the parser is in a handler body
MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s)
CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE
IS_INVOKED= 32; // Is set if this sp_head is being used.
int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
uint m_flags; // Boolean attributes of a stored routine
enum enum_field_types m_returns; // For FUNCTIONs only
Field::geometry_type m_geom_returns;
CHARSET_INFO *m_returns_cs; // For FUNCTIONs only
TYPELIB *m_returns_typelib; // For FUNCTIONs only
uint m_returns_len; // For FUNCTIONs only
uint m_returns_pack; // For FUNCTIONs only
my_bool m_has_return; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
my_bool m_in_handler; // TRUE if parser in a handler body
uchar *m_tmp_query; // Temporary pointer to sub query string
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics;
@ -265,6 +270,19 @@ public:
bool add_used_tables_to_table_list(THD *thd,
TABLE_LIST ***query_tables_last_ptr);
/*
Check if this stored routine contains statements disallowed
in a stored function or trigger, and set an appropriate error message
if this is the case.
*/
bool is_not_allowed_in_function(const char *where)
{
if (m_flags & CONTAINS_DYNAMIC_SQL)
my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "Dynamic SQL");
else if (m_flags & MULTI_RESULTS)
my_error(ER_SP_NO_RETSET, MYF(0), where);
return test(m_flags & (CONTAINS_DYNAMIC_SQL|MULTI_RESULTS));
}
private:
MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
@ -290,9 +308,6 @@ private:
*/
HASH m_sptabs;
/* Used for tracking of routine invocations and preventing recursion. */
bool m_is_invoked;
int
execute(THD *thd);

View File

@ -774,6 +774,60 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
}
/*
Issue correct error message in case we found 2 duplicate tables which
prevent some update operation
SYNOPSIS
update_non_unique_table_error()
update table which we try to update
operation name of update operation
duplicate duplicate table which we found
NOTE:
here we hide view underlying tables if we have them
*/
void update_non_unique_table_error(TABLE_LIST *update,
const char *operation,
TABLE_LIST *duplicate)
{
update= update->top_table();
duplicate= duplicate->top_table();
if (!update->view || !duplicate->view ||
update->view == duplicate->view ||
update->view_name.length != duplicate->view_name.length ||
update->view_db.length != duplicate->view_db.length ||
my_strcasecmp(table_alias_charset,
update->view_name.str, duplicate->view_name.str) != 0 ||
my_strcasecmp(table_alias_charset,
update->view_db.str, duplicate->view_db.str) != 0)
{
/*
it is not the same view repeated (but it can be parts of the same copy
of view), so we have to hide underlying tables.
*/
if (update->view)
{
if (update->view == duplicate->view)
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), update->alias, operation);
else
my_error(ER_VIEW_PREVENT_UPDATE, MYF(0),
(duplicate->view ? duplicate->alias : update->alias),
operation, update->alias);
return;
}
if (duplicate->view)
{
my_error(ER_VIEW_PREVENT_UPDATE, MYF(0), duplicate->alias, operation,
update->alias);
return;
}
}
my_error(ER_UPDATE_TABLE_USED, MYF(0), update->alias);
}
TABLE **find_temporary_table(THD *thd, const char *db, const char *table_name)
{
char key[MAX_DBKEY_LENGTH];
@ -1810,7 +1864,7 @@ err:
if (thd->net.last_errno == ER_NO_SUCH_TABLE &&
table_desc && table_desc->belong_to_view)
{
TABLE_LIST * view= table_desc->belong_to_view;
TABLE_LIST *view= table_desc->belong_to_view;
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0), view->view_db.str, view->view_name.str);
}
@ -3463,7 +3517,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
table_ref_1->alias, table_ref_2->alias));
*found_using_fields= 0;
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
/*
TABLE_LIST::join_columns could be allocated by the previous call to
@ -3630,7 +3684,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
err:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(result);
}
@ -3688,7 +3742,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
DBUG_ASSERT(!natural_using_join->join_columns);
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
if (!(non_join_columns= new List<Natural_join_column>) ||
!(natural_using_join->join_columns= new List<Natural_join_column>))
@ -3773,7 +3827,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
err:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(result);
}
@ -3818,7 +3872,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref,
DBUG_ENTER("store_top_level_join_columns");
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
/* Call the procedure recursively for each nested table reference. */
if (table_ref->nested_join)
@ -3931,7 +3985,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref,
err:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(result);
}
@ -4030,7 +4084,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
Don't use arena if we are not in prepared statements or stored procedures
For PS/SP we have to use arena to remember the changes
*/
arena= thd->change_arena_if_needed(&backup);
arena= thd->activate_stmt_arena_if_needed(&backup);
while (wild_num && (item= it++))
{
@ -4058,7 +4112,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
any_privileges))
{
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
DBUG_RETURN(-1);
}
if (sum_func_list)
@ -4080,7 +4134,7 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
select_lex->with_wild= 0;
select_lex->item_list= fields;
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
}
DBUG_RETURN(0);
}
@ -4218,9 +4272,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
{
TABLE *table= table_list->table;
if (first_select_table &&
(table_list->belong_to_view ?
table_list->belong_to_view :
table_list) == first_select_table)
table_list->top_table() == first_select_table)
{
/* new counting for SELECT of INSERT ... SELECT command */
first_select_table= 0;
@ -4258,15 +4310,15 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
if (table_list->ancestor)
{
DBUG_ASSERT(table_list->view);
Query_arena *arena= thd->current_arena, backup;
Query_arena *arena= thd->stmt_arena, backup;
bool res;
if (arena->is_conventional())
arena= 0; // For easier test
else
thd->set_n_backup_item_arena(arena, &backup);
thd->set_n_backup_active_arena(arena, &backup);
res= table_list->setup_ancestor(thd);
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
if (res)
DBUG_RETURN(1);
}
@ -4347,7 +4399,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
bool found;
char name_buff[NAME_LEN+1];
DBUG_ENTER("insert_fields");
DBUG_PRINT("arena", ("current arena: 0x%lx", (ulong)thd->current_arena));
DBUG_PRINT("arena", ("stmt arena: 0x%lx", (ulong)thd->stmt_arena));
if (db_name && lower_case_table_names)
{
@ -4557,7 +4609,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
COND **conds)
{
SELECT_LEX *select_lex= thd->lex->current_select;
Query_arena *arena= thd->current_arena, backup;
Query_arena *arena= thd->stmt_arena, backup;
TABLE_LIST *table= NULL; // For HP compilers
/*
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
@ -4621,9 +4673,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
/* process CHECK OPTION */
if (it_is_update)
{
TABLE_LIST *view= table->belong_to_view;
if (!view)
view= table;
TABLE_LIST *view= table->top_table();
if (view->effective_with_check)
{
if (view->prepare_check_option(thd))
@ -4633,7 +4683,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
}
}
if (!thd->current_arena->is_conventional())
if (!thd->stmt_arena->is_conventional())
{
/*
We are in prepared statement preparation code => we should store
@ -4648,7 +4698,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
err:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
err_no_arena:
DBUG_RETURN(1);
}

View File

@ -180,7 +180,7 @@ THD::THD()
in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
spcont(NULL)
{
current_arena= this;
stmt_arena= this;
host= user= priv_user= db= ip= 0;
catalog= (char*)"std"; // the only catalog we have for now
host_or_ip= "connecting host";
@ -551,11 +551,6 @@ void THD::cleanup_after_query()
}
/* Free Items that were created during this execution */
free_items();
/*
In the rest of code we assume that free_list never points to garbage:
Keep this predicate true.
*/
free_list= 0;
}
/*
@ -794,7 +789,7 @@ struct Item_change_record: public ilink
/*
Register an item tree tree transformation, performed by the query
optimizer. We need a pointer to runtime_memroot because it may be !=
thd->mem_root (due to possible set_n_backup_item_arena called for thd).
thd->mem_root (due to possible set_n_backup_active_arena called for thd).
*/
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
@ -1602,13 +1597,13 @@ void THD::end_statement()
}
void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
{
DBUG_ENTER("Query_arena::set_n_backup_item_arena");
DBUG_ENTER("THD::set_n_backup_active_arena");
DBUG_ASSERT(backup->is_backup_arena == FALSE);
backup->set_item_arena(this);
set_item_arena(set);
backup->set_query_arena(this);
set_query_arena(set);
#ifndef DBUG_OFF
backup->is_backup_arena= TRUE;
#endif
@ -1616,19 +1611,19 @@ void Query_arena::set_n_backup_item_arena(Query_arena *set, Query_arena *backup)
}
void Query_arena::restore_backup_item_arena(Query_arena *set, Query_arena *backup)
void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
{
DBUG_ENTER("Query_arena::restore_backup_item_arena");
DBUG_ENTER("THD::restore_active_arena");
DBUG_ASSERT(backup->is_backup_arena);
set->set_item_arena(this);
set_item_arena(backup);
set->set_query_arena(this);
set_query_arena(backup);
#ifndef DBUG_OFF
backup->is_backup_arena= FALSE;
#endif
DBUG_VOID_RETURN;
}
void Query_arena::set_item_arena(Query_arena *set)
void Query_arena::set_query_arena(Query_arena *set)
{
mem_root= set->mem_root;
free_list= set->free_list;
@ -1686,23 +1681,17 @@ Statement_map::Statement_map() :
NULL,MYF(0));
}
int Statement_map::insert(Statement *statement)
{
int rc= my_hash_insert(&st_hash, (byte *) statement);
if (rc == 0)
last_found_statement= statement;
if (statement->name.str)
{
/*
If there is a statement with the same name, remove it. It is ok to
remove old and fail to insert new one at the same time.
*/
Statement *old_stmt;
if ((old_stmt= find_by_name(&statement->name)))
erase(old_stmt);
if ((rc= my_hash_insert(&names_hash, (byte*)statement)))
hash_delete(&st_hash, (byte*)statement);
}
if (rc == 0)
last_found_statement= statement;
return rc;
}

View File

@ -735,9 +735,7 @@ public:
return ptr;
}
void set_n_backup_item_arena(Query_arena *set, Query_arena *backup);
void restore_backup_item_arena(Query_arena *set, Query_arena *backup);
void set_item_arena(Query_arena *set);
void set_query_arena(Query_arena *set);
void free_items();
};
@ -1239,16 +1237,16 @@ public:
/*
A permanent memory area of the statement. For conventional
execution, the parsed tree and execution runtime reside in the same
memory root. In this case current_arena points to THD. In case of
memory root. In this case stmt_arena points to THD. In case of
a prepared statement or a stored procedure statement, thd->mem_root
conventionally points to runtime memory, and thd->current_arena
conventionally points to runtime memory, and thd->stmt_arena
points to the memory of the PS/SP, where the parsed tree of the
statement resides. Whenever you need to perform a permanent
transformation of a parsed tree, you should allocate new memory in
current_arena, to allow correct re-execution of PS/SP.
Note: in the parser, current_arena == thd, even for PS/SP.
stmt_arena, to allow correct re-execution of PS/SP.
Note: in the parser, stmt_arena == thd, even for PS/SP.
*/
Query_arena *current_arena;
Query_arena *stmt_arena;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
@ -1476,7 +1474,7 @@ public:
}
inline bool fill_derived_tables()
{
return !current_arena->is_stmt_prepare() && !lex->only_view_structure();
return !stmt_arena->is_stmt_prepare() && !lex->only_view_structure();
}
inline gptr trans_alloc(unsigned int size)
{
@ -1515,17 +1513,16 @@ public:
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
inline Query_arena *change_arena_if_needed(Query_arena *backup)
inline Query_arena *activate_stmt_arena_if_needed(Query_arena *backup)
{
/*
use new arena if we are in a prepared statements and we have not
already changed to use this arena.
Use the persistent arena if we are in a prepared statement or a stored
procedure statement and we have not already changed to use this arena.
*/
if (!current_arena->is_conventional() &&
mem_root != current_arena->mem_root)
if (!stmt_arena->is_conventional() && mem_root != stmt_arena->mem_root)
{
set_n_backup_item_arena(current_arena, backup);
return current_arena;
set_n_backup_active_arena(stmt_arena, backup);
return stmt_arena;
}
return 0;
}
@ -1533,7 +1530,7 @@ public:
void change_item_tree(Item **place, Item *new_value)
{
/* TODO: check for OOM condition here */
if (!current_arena->is_conventional())
if (!stmt_arena->is_conventional())
nocheck_register_item_tree_change(place, *place, mem_root);
*place= new_value;
}
@ -1565,11 +1562,13 @@ public:
}
void set_status_var_init();
bool is_context_analysis_only()
{ return current_arena->is_stmt_prepare() || lex->view_prepare_mode; }
{ return stmt_arena->is_stmt_prepare() || lex->view_prepare_mode; }
void reset_n_backup_open_tables_state(Open_tables_state *backup);
void restore_backup_open_tables_state(Open_tables_state *backup);
void reset_sub_statement_state(Sub_statement_state *backup, uint new_state);
void restore_sub_statement_state(Sub_statement_state *backup);
void set_n_backup_active_arena(Query_arena *set, Query_arena *backup);
void restore_active_arena(Query_arena *set, Query_arena *backup);
};

View File

@ -340,10 +340,13 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
DBUG_RETURN(TRUE);
}
if (unique_table(table_list, table_list->next_global))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
DBUG_RETURN(TRUE);
TABLE_LIST *duplicate;
if ((duplicate= unique_table(table_list, table_list->next_global)))
{
update_non_unique_table_error(table_list, "DELETE", duplicate);
DBUG_RETURN(TRUE);
}
}
select_lex->fix_prepare_information(thd, conds);
DBUG_RETURN(FALSE);
@ -426,11 +429,15 @@ bool mysql_multi_delete_prepare(THD *thd)
Check that table from which we delete is not used somewhere
inside subqueries/view.
*/
if (unique_table(target_tbl->correspondent_table, lex->query_tables))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0),
target_tbl->correspondent_table->table_name);
DBUG_RETURN(TRUE);
TABLE_LIST *duplicate;
if ((duplicate= unique_table(target_tbl->correspondent_table,
lex->query_tables)))
{
update_non_unique_table_error(target_tbl->correspondent_table,
"DELETE", duplicate);
DBUG_RETURN(TRUE);
}
}
}
DBUG_RETURN(FALSE);

View File

@ -930,9 +930,10 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
if (!select_insert)
{
Item *fake_conds= 0;
if (unique_table(table_list, table_list->next_global))
TABLE_LIST *duplicate;
if ((duplicate= unique_table(table_list, table_list->next_global)))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
update_non_unique_table_error(table_list, "INSERT", duplicate);
DBUG_RETURN(TRUE);
}
select_lex->fix_prepare_information(thd, &fake_conds);
@ -1207,9 +1208,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
bool view= FALSE;
if (table_list)
{
table_list= (table_list->belong_to_view ?
table_list->belong_to_view :
table_list);
table_list= table_list->top_table();
view= test(table_list->view);
}
if (view)

View File

@ -128,6 +128,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->update_list.empty();
lex->param_list.empty();
lex->view_list.empty();
lex->prepared_stmt_params.empty();
lex->unit.next= lex->unit.master=
lex->unit.link_next= lex->unit.return_to= 0;
lex->unit.prev= lex->unit.link_prev= 0;
@ -143,6 +144,7 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->describe= 0;
lex->subqueries= FALSE;
lex->view_prepare_mode= FALSE;
lex->stmt_prepare_mode= FALSE;
lex->derived_tables= 0;
lex->lock_option= TL_READ;
lex->found_semicolon= 0;
@ -569,8 +571,7 @@ int yylex(void *arg, void *yythd)
its value in a query for the binlog, the query must stay
grammatically correct.
*/
else if (c == '?' && ((THD*) yythd)->command == COM_STMT_PREPARE &&
!ident_map[yyPeek()])
else if (c == '?' && lex->stmt_prepare_mode && !ident_map[yyPeek()])
return(PARAM_MARKER);
return((int) c);
@ -982,7 +983,7 @@ int yylex(void *arg, void *yythd)
{
THD* thd= (THD*)yythd;
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
(thd->command != COM_STMT_PREPARE))
!lex->stmt_prepare_mode)
{
lex->safe_to_cache_query= 0;
lex->found_semicolon=(char*) lex->ptr;
@ -1505,7 +1506,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
We have to create array in prepared statement memory if it is
prepared statement
*/
Query_arena *arena= thd->current_arena;
Query_arena *arena= thd->stmt_arena;
return (ref_pointer_array=
(Item **)arena->alloc(sizeof(Item*) *
(item_list.elements +
@ -1827,7 +1828,7 @@ void st_select_lex_unit::set_limit(SELECT_LEX *sl)
{
ha_rows select_limit_val;
DBUG_ASSERT(! thd->current_arena->is_stmt_prepare());
DBUG_ASSERT(! thd->stmt_arena->is_stmt_prepare());
select_limit_val= (ha_rows)(sl->select_limit ? sl->select_limit->val_uint() :
HA_POS_ERROR);
offset_limit_cnt= (ha_rows)(sl->offset_limit ? sl->offset_limit->val_uint() :
@ -2039,7 +2040,7 @@ void st_lex::cleanup_after_one_table_open()
void st_select_lex::fix_prepare_information(THD *thd, Item **conds)
{
if (!thd->current_arena->is_conventional() && first_execution)
if (!thd->stmt_arena->is_conventional() && first_execution)
{
first_execution= 0;
if (*conds)

View File

@ -824,6 +824,11 @@ typedef struct st_lex
to an .frm file. We need this definition to stay untouched.
*/
bool view_prepare_mode;
/*
TRUE if we're parsing a prepared statement: in this mode
we should allow placeholders and disallow multistatements.
*/
bool stmt_prepare_mode;
bool safe_to_cache_query;
bool subqueries, ignore;
bool variables_used;

View File

@ -175,6 +175,9 @@ static bool begin_trans(THD *thd)
}
#ifdef HAVE_REPLICATION
/*
Returns true if all tables should be ignored
*/
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
{
return (rpl_filter->is_on() && tables &&
@ -1645,7 +1648,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_STMT_PREPARE:
{
mysql_stmt_prepare(thd, packet, packet_length, 0);
mysql_stmt_prepare(thd, packet, packet_length);
break;
}
case COM_STMT_CLOSE:
@ -1665,6 +1668,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *packet_end= thd->query + thd->query_length;
mysql_log.write(thd,command,"%s",thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
mysql_parse(thd,thd->query, thd->query_length);
while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error)
@ -2221,7 +2228,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
TRUE error; In this case thd->fatal_error is set
*/
bool alloc_query(THD *thd, char *packet, ulong packet_length)
bool alloc_query(THD *thd, const char *packet, uint packet_length)
{
packet_length--; // Remove end null
/* Remove garbage at start and end of query */
@ -2230,7 +2237,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
packet++;
packet_length--;
}
char *pos=packet+packet_length; // Point at end null
const char *pos= packet + packet_length; // Point at end null
while (packet_length > 0 &&
(pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1])))
{
@ -2251,11 +2258,25 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
thd->packet.shrink(thd->variables.net_buffer_length);
thd->convert_buffer.shrink(thd->variables.net_buffer_length);
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
return FALSE;
}
static void reset_one_shot_variables(THD *thd)
{
thd->variables.character_set_client=
global_system_variables.character_set_client;
thd->variables.collation_connection=
global_system_variables.collation_connection;
thd->variables.collation_database=
global_system_variables.collation_database;
thd->variables.collation_server=
global_system_variables.collation_server;
thd->update_charset();
thd->variables.time_zone=
global_system_variables.time_zone;
thd->one_shot_set= 0;
}
/****************************************************************************
** mysql_execute_command
@ -2339,16 +2360,22 @@ mysql_execute_command(THD *thd)
/*
Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated.
Exception is DROP TEMPORARY TABLE IF EXISTS: we always execute it
(otherwise we have stale files on slave caused by exclusion of one tmp
table).
Exceptions are:
- SET: we always execute it (Not that many SET commands exists in
the binary log anyway -- only 4.1 masters write SET statements,
in 5.0 there are no SET statements in the binary log)
- DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we
have stale files on slave caused by exclusion of one tmp table).
*/
if (!(lex->sql_command == SQLCOM_DROP_TABLE &&
if (!(lex->sql_command == SQLCOM_SET_OPTION) &&
!(lex->sql_command == SQLCOM_DROP_TABLE &&
lex->drop_temporary && lex->drop_if_exists) &&
all_tables_not_ok(thd, all_tables))
{
/* we warn the slave SQL thread */
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
reset_one_shot_variables(thd);
DBUG_RETURN(0);
}
#ifndef TO_BE_DELETED
@ -2445,112 +2472,17 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_PREPARE:
{
char *query_str;
uint query_len;
if (lex->prepared_stmt_code_is_varref)
{
/* This is PREPARE stmt FROM @var. */
String str;
CHARSET_INFO *to_cs= thd->variables.collation_connection;
bool need_conversion;
user_var_entry *entry;
String *pstr= &str;
uint32 unused;
/*
Convert @var contents to string in connection character set. Although
it is known that int/real/NULL value cannot be a valid query we still
convert it for error messages to uniform.
*/
if ((entry=
(user_var_entry*)hash_search(&thd->user_vars,
(byte*)lex->prepared_stmt_code.str,
lex->prepared_stmt_code.length))
&& entry->value)
{
my_bool is_var_null;
pstr= entry->val_str(&is_var_null, &str, NOT_FIXED_DEC);
/*
NULL value of variable checked early as entry->value so here
we can't get NULL in normal conditions
*/
DBUG_ASSERT(!is_var_null);
if (!pstr)
goto error;
}
else
{
/*
variable absent or equal to NULL, so we need to set variable to
something reasonable to get readable error message during parsing
*/
str.set("NULL", 4, &my_charset_latin1);
}
need_conversion=
String::needs_conversion(pstr->length(), pstr->charset(),
to_cs, &unused);
query_len= need_conversion? (pstr->length() * to_cs->mbmaxlen) :
pstr->length();
if (!(query_str= alloc_root(thd->mem_root, query_len+1)))
goto error;
if (need_conversion)
{
uint dummy_errors;
query_len= copy_and_convert(query_str, query_len, to_cs,
pstr->ptr(), pstr->length(),
pstr->charset(), &dummy_errors);
}
else
memcpy(query_str, pstr->ptr(), pstr->length());
query_str[query_len]= 0;
}
else
{
query_str= lex->prepared_stmt_code.str;
query_len= lex->prepared_stmt_code.length;
DBUG_PRINT("info", ("PREPARE: %.*s FROM '%.*s' \n",
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str,
query_len, query_str));
}
thd->command= COM_STMT_PREPARE;
if (!(res= mysql_stmt_prepare(thd, query_str, query_len + 1,
&lex->prepared_stmt_name)))
send_ok(thd, 0L, 0L, "Statement prepared");
mysql_sql_stmt_prepare(thd);
break;
}
case SQLCOM_EXECUTE:
{
DBUG_PRINT("info", ("EXECUTE: %.*s\n",
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str));
mysql_sql_stmt_execute(thd, &lex->prepared_stmt_name);
lex->prepared_stmt_params.empty();
mysql_sql_stmt_execute(thd);
break;
}
case SQLCOM_DEALLOCATE_PREPARE:
{
Statement* stmt;
DBUG_PRINT("info", ("DEALLOCATE PREPARE: %.*s\n",
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str));
/* We account deallocate in the same manner as mysql_stmt_close */
statistic_increment(thd->status_var.com_stmt_close, &LOCK_status);
if ((stmt= thd->stmt_map.find_by_name(&lex->prepared_stmt_name)))
{
thd->stmt_map.erase(stmt);
send_ok(thd);
}
else
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
lex->prepared_stmt_name.length,
lex->prepared_stmt_name.str,
"DEALLOCATE PREPARE");
goto error;
}
mysql_sql_stmt_close(thd);
break;
}
case SQLCOM_DO:
@ -2859,12 +2791,15 @@ mysql_execute_command(THD *thd)
Is table which we are changing used somewhere in other parts
of query
*/
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
unique_table(create_table, select_tables))
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->table_name);
res= 1;
goto end_with_restart_wait;
TABLE_LIST *duplicate;
if ((duplicate= unique_table(create_table, select_tables)))
{
update_non_unique_table_error(create_table, "CREATE", duplicate);
res= 1;
goto end_with_restart_wait;
}
}
/* If we create merge table, we have to test tables in merge, too */
if (lex->create_info.used_fields & HA_CREATE_USED_UNION)
@ -2874,9 +2809,10 @@ mysql_execute_command(THD *thd)
tab;
tab= tab->next_local)
{
if (unique_table(tab, select_tables))
TABLE_LIST *duplicate;
if ((duplicate= unique_table(tab, select_tables)))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), tab->table_name);
update_non_unique_table_error(tab, "CREATE", duplicate);
res= 1;
goto end_with_restart_wait;
}
@ -3576,6 +3512,7 @@ end_with_restore_list:
!rpl_filter->db_ok_with_wild_table(lex->name)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
reset_one_shot_variables(thd);
break;
}
#endif
@ -3610,6 +3547,7 @@ end_with_restore_list:
!rpl_filter->db_ok_with_wild_table(lex->name)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
reset_one_shot_variables(thd);
break;
}
#endif
@ -3650,6 +3588,7 @@ end_with_restore_list:
!rpl_filter->db_ok_with_wild_table(lex->name)))
{
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
reset_one_shot_variables(thd);
break;
}
#endif
@ -4100,7 +4039,7 @@ end_with_restore_list:
}
#endif
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
!lex->sphead->m_has_return)
!(lex->sphead->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), name);
delete lex->sphead;
@ -4189,15 +4128,31 @@ end_with_restore_list:
ha_rows select_limit;
/* bits that should be cleared in thd->server_status */
uint bits_to_be_cleared= 0;
/*
Check that the stored procedure doesn't contain Dynamic SQL
and doesn't return result sets: such stored procedures can't
be called from a function or trigger.
*/
if (thd->in_sub_stmt)
{
const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ?
"trigger" : "function");
if (sp->is_not_allowed_in_function(where))
goto error;
}
#ifndef EMBEDDED_LIBRARY
my_bool nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
#endif
if (sp->m_multi_results)
if (sp->m_flags & sp_head::MULTI_RESULTS)
{
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
{
/*
The client does not support multiple result sets being sent
back
*/
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
@ -4241,7 +4196,7 @@ end_with_restore_list:
thd->row_count_func= 0;
/*
We never write CALL statements int binlog:
We never write CALL statements into binlog:
- If the mode is non-prelocked, each statement will be logged
separately.
- If the mode is prelocked, the invoking statement will care
@ -4706,30 +4661,19 @@ end_with_restore_list:
}
thd->proc_info="query end";
/* Two binlog-related cleanups: */
if (thd->one_shot_set)
{
/*
If this is a SET, do nothing. This is to allow mysqlbinlog to print
many SET commands (in this case we want the charset temp setting to
live until the real query). This is also needed so that SET
CHARACTER_SET_CLIENT... does not cancel itself immediately.
*/
if (lex->sql_command != SQLCOM_SET_OPTION)
{
thd->variables.character_set_client=
global_system_variables.character_set_client;
thd->variables.collation_connection=
global_system_variables.collation_connection;
thd->variables.collation_database=
global_system_variables.collation_database;
thd->variables.collation_server=
global_system_variables.collation_server;
thd->update_charset();
thd->variables.time_zone=
global_system_variables.time_zone;
thd->one_shot_set= 0;
}
}
/*
Reset system variables temporarily modified by SET ONE SHOT.
Exception: If this is a SET, do nothing. This is to allow
mysqlbinlog to print many SET commands (in this case we want the
charset temp setting to live until the real query). This is also
needed so that SET CHARACTER_SET_CLIENT... does not cancel itself
immediately.
*/
if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
reset_one_shot_variables(thd);
/*
The return value for ROW_COUNT() is "implementation dependent" if
@ -5262,7 +5206,7 @@ mysql_new_select(LEX *lex, bool move_down)
it's a constant one. The flag is switched off in the end of
mysql_stmt_prepare.
*/
if (thd->current_arena->is_stmt_prepare())
if (thd->stmt_arena->is_stmt_prepare())
select_lex->uncacheable|= UNCACHEABLE_PREPARE;
if (move_down)
{
@ -6068,7 +6012,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->db= empty_c_string;
ptr->db_length= 0;
}
if (thd->current_arena->is_stmt_prepare_or_first_sp_execute())
if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
ptr->db= thd->strdup(ptr->db);
ptr->alias= alias_str;
@ -7288,7 +7232,7 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables,
against the opened tables to ensure we don't use a table that is part
of the view (which can only be done after the table has been opened).
*/
if (thd->current_arena->is_stmt_prepare_or_first_sp_execute())
if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
{
/*
For temporary tables we don't have to check if the created table exists

File diff suppressed because it is too large Load Diff

View File

@ -581,11 +581,11 @@ JOIN::optimize()
MEMROOT for prepared statements and stored procedures.
*/
Query_arena *arena= thd->current_arena, backup;
Query_arena *arena= thd->stmt_arena, backup;
if (arena->is_conventional())
arena= 0; // For easier test
else
thd->set_n_backup_item_arena(arena, &backup);
thd->set_n_backup_active_arena(arena, &backup);
sel->first_cond_optimization= 0;
@ -595,7 +595,7 @@ JOIN::optimize()
sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
}
conds= optimize_cond(this, conds, join_list, &cond_value);
@ -1756,7 +1756,7 @@ Cursor::init_from_thd(THD *thd)
things that are already allocated in thd->mem_root for Cursor::fetch()
*/
main_mem_root= *thd->mem_root;
state= thd->current_arena->state;
state= thd->stmt_arena->state;
/* Allocate new memory root for thd */
init_sql_alloc(thd->mem_root,
thd->variables.query_alloc_block_size,
@ -1883,7 +1883,7 @@ Cursor::fetch(ulong num_rows)
thd->query_id= query_id;
thd->change_list= change_list;
/* save references to memory, allocated during fetch */
thd->set_n_backup_item_arena(this, &backup_arena);
thd->set_n_backup_active_arena(this, &backup_arena);
for (info= ht_info; info->read_view ; info++)
(info->ht->set_cursor_read_view)(info->read_view);
@ -1902,7 +1902,7 @@ Cursor::fetch(ulong num_rows)
ha_release_temporary_latches(thd);
#endif
/* Grab free_list here to correctly free it in close */
thd->restore_backup_item_arena(this, &backup_arena);
thd->restore_active_arena(this, &backup_arena);
for (info= ht_info; info->read_view; info++)
(info->ht->set_cursor_read_view)(0);

View File

@ -3632,7 +3632,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
}
List_iterator_fast<Item> it(sel->item_list);
if (!(transl=
(Field_translator*)(thd->current_arena->
(Field_translator*)(thd->stmt_arena->
alloc(sel->item_list.elements *
sizeof(Field_translator)))))
{

View File

@ -287,7 +287,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
all collations together for UNION.
*/
List_iterator_fast<Item> tp(types);
Query_arena *arena= thd->current_arena;
Query_arena *arena= thd->stmt_arena;
Item *type;
ulonglong create_options;
@ -332,7 +332,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
{
Field **field;
Query_arena *tmp_arena,backup;
tmp_arena= thd->change_arena_if_needed(&backup);
tmp_arena= thd->activate_stmt_arena_if_needed(&backup);
for (field= table->field; *field; field++)
{
@ -340,12 +340,12 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!item || item_list.push_back(item))
{
if (tmp_arena)
thd->restore_backup_item_arena(tmp_arena, &backup);
thd->restore_active_arena(tmp_arena, &backup);
DBUG_RETURN(TRUE);
}
}
if (tmp_arena)
thd->restore_backup_item_arena(tmp_arena, &backup);
thd->restore_active_arena(tmp_arena, &backup);
if (arena->is_stmt_prepare_or_first_sp_execute())
{
/* prepare fake select to initialize it correctly */

View File

@ -671,10 +671,14 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE);
/* Check that we are not using table that we are updating in a sub select */
if (unique_table(table_list, table_list->next_global))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
DBUG_RETURN(TRUE);
TABLE_LIST *duplicate;
if ((duplicate= unique_table(table_list, table_list->next_global)))
{
update_non_unique_table_error(table_list, "UPDATE", duplicate);
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
DBUG_RETURN(TRUE);
}
}
select_lex->fix_prepare_information(thd, conds);
DBUG_RETURN(FALSE);
@ -884,7 +888,7 @@ bool mysql_multi_update_prepare(THD *thd)
{
TABLE *table= tl->table;
TABLE_LIST *tlist;
if (!(tlist= tl->belong_to_view ? tl->belong_to_view : tl)->derived)
if (!(tlist= tl->top_table())->derived)
{
tlist->grant.want_privilege=
(SELECT_ACL & ~tlist->grant.privilege);
@ -893,11 +897,14 @@ bool mysql_multi_update_prepare(THD *thd)
DBUG_PRINT("info", ("table: %s want_privilege: %u", tl->alias,
(uint) table->grant.want_privilege));
if (tl->lock_type != TL_READ &&
tl->lock_type != TL_READ_NO_INSERT &&
unique_table(tl, table_list))
tl->lock_type != TL_READ_NO_INSERT)
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->table_name);
DBUG_RETURN(TRUE);
TABLE_LIST *duplicate;
if ((duplicate= unique_table(tl, table_list)))
{
update_non_unique_table_error(table_list, "UPDATE", duplicate);
DBUG_RETURN(TRUE);
}
}
}

View File

@ -700,11 +700,11 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
For now we assume that tables will not be changed during PS life (it
will be TRUE as far as we make new table cache).
*/
Query_arena *arena= thd->current_arena, backup;
Query_arena *arena= thd->stmt_arena, backup;
if (arena->is_conventional())
arena= 0;
else
thd->set_n_backup_item_arena(arena, &backup);
thd->set_n_backup_active_arena(arena, &backup);
/* init timestamp */
if (!table->timestamp.str)
@ -774,9 +774,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
}
if (!res && !thd->is_fatal_error)
{
TABLE_LIST *top_view= (table->belong_to_view ?
table->belong_to_view :
table);
TABLE_LIST *top_view= table->top_table();
TABLE_LIST *view_tables= lex->query_tables;
TABLE_LIST *view_tables_tail= 0;
TABLE_LIST *tbl;
@ -997,13 +995,13 @@ ok:
ok2:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
thd->lex= old_lex;
DBUG_RETURN(0);
err:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
delete table->view;
table->view= 0; // now it is not VIEW placeholder
thd->lex= old_lex;
@ -1145,8 +1143,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
thd->lex->select_lex.select_limit == 0)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table;
if (view->belong_to_view)
view= view->belong_to_view;
view= view->top_table();
trans= view->field_translation;
key_info_end= (key_info= table->key_info)+ table->s->keys;

View File

@ -937,16 +937,11 @@ deallocate:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
if (thd->command == COM_STMT_PREPARE)
if (lex->stmt_prepare_mode)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "DEALLOCATE");
YYABORT;
}
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
lex->prepared_stmt_name= $3;
};
@ -962,16 +957,11 @@ prepare:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
if (thd->command == COM_STMT_PREPARE)
if (lex->stmt_prepare_mode)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "PREPARE");
YYABORT;
}
lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2;
};
@ -997,16 +987,11 @@ execute:
{
THD *thd=YYTHD;
LEX *lex= thd->lex;
if (thd->command == COM_STMT_PREPARE)
if (lex->stmt_prepare_mode)
{
yyerror(ER(ER_SYNTAX_ERROR));
YYABORT;
}
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "EXECUTE");
YYABORT;
}
lex->sql_command= SQLCOM_EXECUTE;
lex->prepared_stmt_name= $2;
}
@ -1340,11 +1325,8 @@ create:
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
sp->restore_thd_mem_root(YYTHD);
if (sp->m_multi_results)
{
my_error(ER_SP_NO_RETSET, MYF(0), "trigger");
YYABORT;
}
if (sp->is_not_allowed_in_function("trigger"))
YYABORT;
/*
We have to do it after parsing trigger body, because some of
@ -1497,11 +1479,9 @@ create_function_tail:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if (sp->m_multi_results)
{
my_error(ER_SP_NO_RETSET, MYF(0), "function");
YYABORT;
}
if (sp->is_not_allowed_in_function("function"))
YYABORT;
if (sp->check_backpatch(YYTHD))
YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
@ -1751,7 +1731,7 @@ sp_decl:
sp->add_instr(i);
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->m_in_handler= TRUE;
sp->m_flags|= sp_head::IN_HANDLER;
}
sp_hcond_list sp_proc_stmt
{
@ -1775,7 +1755,7 @@ sp_decl:
sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
}
lex->sphead->backpatch(hlab);
sp->m_in_handler= FALSE;
sp->m_flags&= ~sp_head::IN_HANDLER;
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= $6;
ctx->add_handlers($6);
@ -1987,12 +1967,7 @@ sp_proc_stmt:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
if ((lex->sql_command == SQLCOM_SELECT && !lex->result) ||
sp_multi_results_command(lex->sql_command))
{
/* We maybe have one or more SELECT without INTO */
sp->m_multi_results= TRUE;
}
sp->m_flags|= sp_get_flags_for_command(lex);
if (lex->sql_command == SQLCOM_CHANGE_DB)
{ /* "USE db" doesn't work in a procedure */
my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
@ -2042,14 +2017,14 @@ sp_proc_stmt:
i= new sp_instr_freturn(sp->instructions(), lex->spcont,
$3, sp->m_returns, lex);
sp->add_instr(i);
sp->m_has_return= TRUE;
sp->m_flags|= sp_head::HAS_RETURN;
}
sp->restore_lex(YYTHD);
}
| IF sp_if END IF {}
| CASE_SYM WHEN_SYM
{
Lex->sphead->m_simple_case= FALSE;
Lex->sphead->m_flags&= ~sp_head::IN_SIMPLE_CASE;
}
sp_case END CASE_SYM {}
| CASE_SYM
@ -2069,7 +2044,7 @@ sp_proc_stmt:
lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in);
lex->sphead->add_instr(i);
lex->sphead->m_simple_case= TRUE;
lex->sphead->m_flags|= sp_head::IN_SIMPLE_CASE;
lex->sphead->restore_lex(YYTHD);
}
sp_case END CASE_SYM
@ -2383,7 +2358,7 @@ sp_case:
uint ip= sp->instructions();
sp_instr_jump_if_not *i;
if (! sp->m_simple_case)
if (! (sp->m_flags & sp_head::IN_SIMPLE_CASE))
i= new sp_instr_jump_if_not(ip, ctx, $2, lex);
else
{ /* Simple case: <caseval> = <whenval> */

View File

@ -1815,7 +1815,7 @@ bool st_table_list::setup_ancestor(THD *thd)
/* Create view fields translation table */
if (!(transl=
(Field_translator*)(thd->current_arena->
(Field_translator*)(thd->stmt_arena->
alloc(select->item_list.elements *
sizeof(Field_translator)))))
{
@ -1891,8 +1891,8 @@ bool st_table_list::prep_where(THD *thd, Item **conds,
if (!no_where_clause && !where_processed)
{
TABLE_LIST *tbl= this;
Query_arena *arena= thd->current_arena, backup;
arena= thd->change_arena_if_needed(&backup); // For easier test
Query_arena *arena= thd->stmt_arena, backup;
arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test
/* Go up to join tree and try to find left join */
for (; tbl; tbl= tbl->embedding)
@ -1912,7 +1912,7 @@ bool st_table_list::prep_where(THD *thd, Item **conds,
if (tbl == 0)
*conds= and_conds(*conds, where);
if (arena)
thd->restore_backup_item_arena(arena, &backup);
thd->restore_active_arena(arena, &backup);
where_processed= TRUE;
}
}
@ -2091,7 +2091,7 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
{
if (check_option && check_option->val_int() == 0)
{
TABLE_LIST *view= (belong_to_view ? belong_to_view : this);
TABLE_LIST *view= top_table();
if (ignore_failure)
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,

View File

@ -609,6 +609,8 @@ typedef struct st_table_list
st_table_list *first_leaf_for_name_resolution();
st_table_list *last_leaf_for_name_resolution();
bool is_leaf_for_name_resolution();
inline st_table_list *top_table()
{ return belong_to_view ? belong_to_view : this; }
inline bool prepare_check_option(THD *thd)
{
bool res= FALSE;

View File

@ -175,6 +175,19 @@ page_rec_is_comp(
/* out: nonzero if in compact format */
const rec_t* rec) /* in: record */
{
#ifdef UNIV_RELEASE_NOT_YET_STABLE
if (UNIV_UNLIKELY((ulint)rec < (ulint)(buf_pool->frame_zero))
|| UNIV_UNLIKELY((ulint)rec >= (ulint)(buf_pool->high_end))) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: trying to read a stray page rec %p\n"
"InnoDB: buf pool start is at %p, end at %p\n",
rec, buf_pool->frame_zero,
buf_pool->high_end);
ut_error;
}
#endif
return(page_is_comp(ut_align_down((rec_t*) rec, UNIV_PAGE_SIZE)));
}

View File

@ -80,6 +80,10 @@ memory is read outside the allocated blocks. */
/* Make a non-inline debug version */
/* You can remove this define when the release is stable. This define adds
some consistency checks to code. They use a little CPU time. */
#define UNIV_RELEASE_NOT_YET_STABLE
/*
#define UNIV_DEBUG
#define UNIV_MEM_DEBUG

View File

@ -513,14 +513,15 @@ handle_new_error:
return(TRUE);
} else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT
} else if (err == DB_DEADLOCK
|| err == DB_LOCK_TABLE_FULL) {
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
trx_general_rollback_for_mysql(trx, FALSE, NULL);
} else if (err == DB_OUT_OF_FILE_SPACE) {
} else if (err == DB_OUT_OF_FILE_SPACE
|| err == DB_LOCK_WAIT_TIMEOUT) {
if (savept) {
/* Roll back the latest, possibly incomplete
insertion or update */

View File

@ -2724,7 +2724,9 @@ row_sel_get_clust_rec_for_mysql(
if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
&& !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
*offsets, trx->read_view)) {
/* The following call returns 'offsets' associated with
'old_vers' */
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
prebuilt, clust_rec,
@ -3055,13 +3057,14 @@ row_search_for_mysql(
cursor 'direction' should be 0. */
{
dict_index_t* index = prebuilt->index;
ibool comp = index->table->comp;
dtuple_t* search_tuple = prebuilt->search_tuple;
btr_pcur_t* pcur = prebuilt->pcur;
trx_t* trx = prebuilt->trx;
dict_index_t* clust_index;
que_thr_t* thr;
rec_t* rec;
rec_t* index_rec;
rec_t* result_rec;
rec_t* clust_rec;
rec_t* old_vers;
ulint err = DB_SUCCESS;
@ -3491,7 +3494,7 @@ rec_loop:
/* PHASE 4: Look for matching records in a loop */
rec = btr_pcur_get_rec(pcur);
ut_ad(!!page_rec_is_comp(rec) == index->table->comp);
ut_ad(!!page_rec_is_comp(rec) == comp);
#ifdef UNIV_SEARCH_DEBUG
/*
fputs("Using ", stderr);
@ -3544,19 +3547,23 @@ rec_loop:
/* Do sanity checks in case our cursor has bumped into page
corruption */
if (page_rec_is_comp(rec)) {
if (comp) {
next_offs = rec_get_next_offs(rec, TRUE);
if (UNIV_UNLIKELY(next_offs < PAGE_NEW_SUPREMUM)) {
goto wrong_offs;
}
} else {
next_offs = rec_get_next_offs(rec, FALSE);
if (UNIV_UNLIKELY(next_offs < PAGE_OLD_SUPREMUM)) {
goto wrong_offs;
}
}
if (UNIV_UNLIKELY(next_offs >= UNIV_PAGE_SIZE - PAGE_DIR)) {
wrong_offs:
wrong_offs:
if (srv_force_recovery == 0 || moves_up == FALSE) {
ut_print_timestamp(stderr);
buf_page_print(buf_frame_align(rec));
@ -3599,6 +3606,9 @@ rec_loop:
goto next_rec;
}
}
/*-------------------------------------------------------------*/
/* Calculate the 'offsets' associated with 'rec' */
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap);
@ -3619,8 +3629,6 @@ rec_loop:
}
}
/*-------------------------------------------------------------*/
/* Note that we cannot trust the up_match value in the cursor at this
place because we can arrive here after moving the cursor! Thus
we have to recompare rec and search_tuple to determine if they
@ -3711,7 +3719,7 @@ rec_loop:
if (!set_also_gap_locks
|| srv_locks_unsafe_for_binlog
|| (unique_search && !UNIV_UNLIKELY(rec_get_deleted_flag(
rec, page_rec_is_comp(rec))))) {
rec, comp)))) {
goto no_gap_lock;
} else {
@ -3767,6 +3775,8 @@ no_gap_lock:
&& !lock_clust_rec_cons_read_sees(rec, index,
offsets, trx->read_view)) {
/* The following call returns 'offsets'
associated with 'old_vers' */
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
prebuilt, rec,
@ -3795,19 +3805,20 @@ no_gap_lock:
is necessary, because we can only get the undo
information via the clustered index record. */
/* Get the clustered index record if needed */
index_rec = rec;
ut_ad(index != clust_index);
goto requires_clust_rec;
}
}
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, page_rec_is_comp(rec)))) {
/* NOTE that at this point rec can be an old version of a clustered
index record built for a consistent read. We cannot assume after this
point that rec is on a buffer pool page. Functions like
page_rec_is_comp() cannot be used! */
/* The record is delete-marked: we can skip it if this is
not a consistent read which might see an earlier version
of a non-clustered index record */
if (UNIV_UNLIKELY(rec_get_deleted_flag(rec, comp))) {
/* The record is delete-marked: we can skip it */
if (srv_locks_unsafe_for_binlog
&& prebuilt->select_lock_type != LOCK_NONE) {
@ -3823,25 +3834,26 @@ no_gap_lock:
goto next_rec;
}
/* Get the clustered index record if needed and if we did
not do the search using the clustered index */
index_rec = rec;
/* Get the clustered index record if needed, if we did not do the
search using the clustered index. */
if (index != clust_index && prebuilt->need_to_access_clustered) {
requires_clust_rec:
/* Before and after this "if" block, "offsets" will be
related to "rec", which may be in a secondary index "index" or
the clustered index ("clust_index"). However, after this
"if" block, "rec" may be pointing to
"clust_rec" of "clust_index". */
/* We use a 'goto' to the preceding label if a consistent
read of a secondary index record requires us to look up old
versions of the associated clustered index record. */
ut_ad(rec_offs_validate(rec, index, offsets));
/* It was a non-clustered index and we must fetch also the
clustered index record */
mtr_has_extra_clust_latch = TRUE;
/* The following call returns 'offsets' associated with
'clust_rec'. Note that 'clust_rec' can be an old version
built for a consistent read. */
err = row_sel_get_clust_rec_for_mysql(prebuilt, index, rec,
thr, &clust_rec,
@ -3858,8 +3870,7 @@ requires_clust_rec:
goto next_rec;
}
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec,
page_rec_is_comp(clust_rec)))) {
if (UNIV_UNLIKELY(rec_get_deleted_flag(clust_rec, comp))) {
/* The record is delete marked: we can skip it */
@ -3879,17 +3890,27 @@ requires_clust_rec:
}
if (prebuilt->need_to_access_clustered) {
rec = clust_rec;
ut_ad(rec_offs_validate(rec, clust_index, offsets));
result_rec = clust_rec;
ut_ad(rec_offs_validate(result_rec, clust_index,
offsets));
} else {
/* We used 'offsets' for the clust rec, recalculate
them for 'rec' */
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
result_rec = rec;
}
} else {
result_rec = rec;
}
/* We found a qualifying row */
ut_ad(rec_offs_validate(rec,
rec == clust_rec ? clust_index : index,
/* We found a qualifying record 'result_rec'. At this point,
'offsets' are associated with 'result_rec'. */
ut_ad(rec_offs_validate(result_rec,
result_rec != rec ? clust_index : index,
offsets));
if ((match_mode == ROW_SEL_EXACT
@ -3910,8 +3931,8 @@ requires_clust_rec:
not cache rows because there the cursor is a scrollable
cursor. */
row_sel_push_cache_row_for_mysql(prebuilt, rec, offsets);
row_sel_push_cache_row_for_mysql(prebuilt, result_rec,
offsets);
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
goto got_row;
@ -3920,13 +3941,14 @@ requires_clust_rec:
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
memcpy(buf + 4, rec - rec_offs_extra_size(offsets),
memcpy(buf + 4, result_rec
- rec_offs_extra_size(offsets),
rec_offs_size(offsets));
mach_write_to_4(buf,
rec_offs_extra_size(offsets) + 4);
} else {
if (!row_sel_store_mysql_rec(buf, prebuilt,
rec, offsets)) {
result_rec, offsets)) {
err = DB_TOO_BIG_RECORD;
goto lock_wait_or_error;
@ -3934,15 +3956,18 @@ requires_clust_rec:
}
if (prebuilt->clust_index_was_generated) {
if (rec != index_rec) {
if (result_rec != rec) {
offsets = rec_get_offsets(
index_rec, index, offsets,
rec, index, offsets,
ULINT_UNDEFINED, &heap);
}
row_sel_store_row_id_to_prebuilt(prebuilt, index_rec,
row_sel_store_row_id_to_prebuilt(prebuilt, rec,
index, offsets);
}
}
/* From this point on, 'offsets' are invalid. */
got_row:
/* We have an optimization to save CPU time: if this is a consistent
read on a unique condition on the clustered index, then we do not
@ -3993,7 +4018,7 @@ next_rec:
if (moves_up) {
if (UNIV_UNLIKELY(!btr_pcur_move_to_next(pcur, &mtr))) {
not_moved:
not_moved:
btr_pcur_store_position(pcur, &mtr);
if (match_mode != 0) {

View File

@ -3194,9 +3194,11 @@ int sort_write_record(MI_SORT_PARAM *sort_param)
break;
case COMPRESSED_RECORD:
reclength=info->packed_length;
length=save_pack_length(block_buff,reclength);
length= save_pack_length((uint) share->pack.version, block_buff,
reclength);
if (info->s->base.blobs)
length+=save_pack_length(block_buff+length,info->blob_length);
length+= save_pack_length((uint) share->pack.version,
block_buff + length, info->blob_length);
if (my_b_write(&info->rec_cache,block_buff,length) ||
my_b_write(&info->rec_cache,(byte*) sort_param->rec_buff,reclength))
{

View File

@ -151,11 +151,12 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
my_errno=HA_ERR_END_OF_FILE;
goto err0;
}
if (memcmp((byte*) header,(byte*) myisam_pack_file_magic,4))
if (memcmp((byte*) header, (byte*) myisam_pack_file_magic, 3))
{
my_errno=HA_ERR_WRONG_IN_RECORD;
goto err0;
}
share->pack.version= header[3];
share->pack.header_length= uint4korr(header+4);
share->min_pack_length=(uint) uint4korr(header+8);
share->max_pack_length=(uint) uint4korr(header+12);
@ -1070,38 +1071,12 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BLOCK_INFO *info, File file,
return BLOCK_FATAL_ERROR;
DBUG_DUMP("header",(byte*) header,ref_length);
}
if (header[0] < 254)
{
info->rec_len=header[0];
head_length=1;
}
else if (header[0] == 254)
{
info->rec_len=uint2korr(header+1);
head_length=3;
}
else
{
info->rec_len=uint3korr(header+1);
head_length=4;
}
head_length= read_pack_length((uint) myisam->s->pack.version, header,
&info->rec_len);
if (myisam->s->base.blobs)
{
if (header[head_length] < 254)
{
info->blob_len=header[head_length];
head_length++;
}
else if (header[head_length] == 254)
{
info->blob_len=uint2korr(header+head_length+1);
head_length+=3;
}
else
{
info->blob_len=uint3korr(header+head_length+1);
head_length+=4;
}
head_length+= read_pack_length((uint) myisam->s->pack.version,
header + head_length, &info->blob_len);
if (!(mi_alloc_rec_buff(myisam,info->rec_len + info->blob_len,
&myisam->rec_buff)))
return BLOCK_FATAL_ERROR; /* not enough memory */
@ -1251,34 +1226,12 @@ void _mi_unmap_file(MI_INFO *info)
static uchar *_mi_mempack_get_block_info(MI_INFO *myisam,MI_BLOCK_INFO *info,
uchar *header)
{
if (header[0] < 254)
info->rec_len= *header++;
else if (header[0] == 254)
{
info->rec_len=uint2korr(header+1);
header+=3;
}
else
{
info->rec_len=uint3korr(header+1);
header+=4;
}
header+= read_pack_length((uint) myisam->s->pack.version, header,
&info->rec_len);
if (myisam->s->base.blobs)
{
if (header[0] < 254)
{
info->blob_len= *header++;
}
else if (header[0] == 254)
{
info->blob_len=uint2korr(header+1);
header+=3;
}
else
{
info->blob_len=uint3korr(header+1);
header+=4;
}
header+= read_pack_length((uint) myisam->s->pack.version, header,
&info->blob_len);
/* mi_alloc_rec_buff sets my_errno on error */
if (!(mi_alloc_rec_buff(myisam, info->blob_len,
&myisam->rec_buff)))
@ -1350,7 +1303,7 @@ static int _mi_read_rnd_mempack_record(MI_INFO *info, byte *buf,
/* Save length of row */
uint save_pack_length(byte *block_buff,ulong length)
uint save_pack_length(uint version, byte *block_buff, ulong length)
{
if (length < 254)
{
@ -1364,6 +1317,46 @@ uint save_pack_length(byte *block_buff,ulong length)
return 3;
}
*(uchar*) block_buff=255;
int3store(block_buff+1,(ulong) length);
return 4;
if (version == 1) /* old format */
{
DBUG_ASSERT(length <= 0xFFFFFF);
int3store(block_buff + 1, (ulong) length);
return 4;
}
else
{
int4store(block_buff + 1, (ulong) length);
return 5;
}
}
uint read_pack_length(uint version, const uchar *buf, ulong *length)
{
if (buf[0] < 254)
{
*length= buf[0];
return 1;
}
else if (buf[0] == 254)
{
*length= uint2korr(buf + 1);
return 3;
}
if (version == 1) /* old format */
{
*length= uint3korr(buf + 1);
return 4;
}
else
{
*length= uint4korr(buf + 1);
return 5;
}
}
uint calc_pack_length(uint version, ulong length)
{
return (length < 254) ? 1 : (length < 65536) ? 3 : (version == 1) ? 4 : 5;
}

View File

@ -27,7 +27,7 @@ LIST *myisam_open_list=0;
uchar NEAR myisam_file_magic[]=
{ (uchar) 254, (uchar) 254,'\007', '\001', };
uchar NEAR myisam_pack_file_magic[]=
{ (uchar) 254, (uchar) 254,'\010', '\001', };
{ (uchar) 254, (uchar) 254,'\010', '\002', };
my_string myisam_log_filename=(char*) "myisam.log";
File myisam_log_file= -1;
uint myisam_quick_table_bits=9;

View File

@ -149,6 +149,7 @@ typedef struct st_mi_blob /* Info of record */
typedef struct st_mi_isam_pack {
ulong header_length;
uint ref_length;
uchar version;
} MI_PACK;
@ -673,7 +674,9 @@ extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info,
extern void mi_report_error(int errcode, const char *file_name);
extern my_bool _mi_memmap_file(MI_INFO *info);
extern void _mi_unmap_file(MI_INFO *info);
extern uint save_pack_length(byte *block_buff,ulong length);
extern uint save_pack_length(uint version, byte *block_buff, ulong length);
extern uint read_pack_length(uint version, const uchar *buf, ulong *length);
extern uint calc_pack_length(uint version, ulong length);
uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite);
char *mi_state_info_read(uchar *ptr, MI_STATE_INFO *state);

View File

@ -2417,6 +2417,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
HUFF_COUNTS *count,*end_count;
HUFF_TREE *tree;
MI_INFO *isam_file=mrg->file[0];
uint pack_version= (uint) isam_file->s->pack.version;
DBUG_ENTER("compress_isam_file");
/* Allocate a buffer for the records (excluding blobs). */
@ -2455,25 +2456,11 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
huff_counts[i].tree->height+huff_counts[i].length_bits;
}
max_calc_length= (max_calc_length + 7) / 8;
if (max_calc_length < 254)
pack_ref_length=1;
else if (max_calc_length <= 65535)
pack_ref_length=3;
else
pack_ref_length=4;
pack_ref_length= calc_pack_length(pack_version, max_calc_length);
record_count=0;
/* 'max_blob_length' is the max length of all blobs of a record. */
pack_blob_length=0;
if (isam_file->s->base.blobs)
{
if (mrg->max_blob_length < 254)
pack_blob_length=1;
else if (mrg->max_blob_length <= 65535)
pack_blob_length=3;
else
pack_blob_length=4;
}
pack_blob_length= isam_file->s->base.blobs ?
calc_pack_length(pack_version, mrg->max_blob_length) : 0;
max_pack_length=pack_ref_length+pack_blob_length;
DBUG_PRINT("fields", ("==="));
@ -2746,9 +2733,10 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
flush_bits();
length=(ulong) ((byte*) file_buffer.pos - record_pos) - max_pack_length;
pack_length=save_pack_length(record_pos,length);
pack_length= save_pack_length(pack_version, record_pos, length);
if (pack_blob_length)
pack_length+=save_pack_length(record_pos+pack_length,tot_blob_length);
pack_length+= save_pack_length(pack_version, record_pos + pack_length,
tot_blob_length);
DBUG_PRINT("fields", ("record: %lu length: %lu blob-length: %lu "
"length-bytes: %lu", (ulong) record_count, length,
tot_blob_length, pack_length));

View File

@ -222,5 +222,6 @@ GSN_PRINT_SIGNATURE(printSCAN_FRAGREQ);
GSN_PRINT_SIGNATURE(printCONTINUEB_NDBFS);
GSN_PRINT_SIGNATURE(printCONTINUEB_DBDIH);
GSN_PRINT_SIGNATURE(printSTART_FRAG_REQ);
#endif

View File

@ -32,6 +32,8 @@ class StartFragReq {
public:
STATIC_CONST( SignalLength = 19 );
friend bool printSTART_FRAG_REQ(FILE *, const Uint32 *, Uint32, Uint16);
private:
Uint32 userPtr;
Uint32 userRef;

View File

@ -33,7 +33,6 @@ EventLoggerBase::~EventLoggerBase()
}
#define QQQQ char *m_text, size_t m_text_len, const Uint32* theData
void getTextConnected(QQQQ) {
@ -434,10 +433,12 @@ void getTextNR_CopyFragsCompleted(QQQQ) {
void getTextLCPFragmentCompleted(QQQQ) {
BaseString::snprintf(m_text, m_text_len,
"Table ID = %u, fragment ID = %u has completed LCP "
"on Node %u",
"on Node %u maxGciStarted: %d maxGciCompleted: %d",
theData[2],
theData[3],
theData[1]);
theData[1],
theData[4],
theData[5]);
}
void getTextTransReportCounters(QQQQ) {
// -------------------------------------------------------------------

View File

@ -198,6 +198,7 @@ SignalDataPrintFunctions[] = {
,{ GSN_ACC_LOCKREQ, printACC_LOCKREQ }
,{ GSN_LQH_TRANSCONF, printLQH_TRANSCONF }
,{ GSN_SCAN_FRAGREQ, printSCAN_FRAGREQ }
,{ GSN_START_FRAGREQ, printSTART_FRAG_REQ }
,{ 0, 0 }
};

View File

@ -17,6 +17,7 @@
#include <RefConvert.hpp>
#include <signaldata/StartRec.hpp>
#include <signaldata/StartFragReq.hpp>
bool
printSTART_REC_REQ(FILE * output,
@ -50,3 +51,27 @@ printSTART_REC_CONF(FILE * output,
return true;
}
bool
printSTART_FRAG_REQ(FILE * output,
const Uint32 * theData,
Uint32 len,
Uint16 recBlockNo)
{
StartFragReq* sig = (StartFragReq*)theData;
fprintf(output, " table: %d frag: %d lcpId: %d lcpNo: %d #nodes: %d \n",
sig->tableId, sig->fragId, sig->lcpId, sig->lcpNo,
sig->noOfLogNodes);
for(Uint32 i = 0; i<sig->noOfLogNodes; i++)
{
fprintf(output, " (node: %d startGci: %d lastGci: %d)",
sig->lqhLogNode[i],
sig->startGci[i],
sig->lastGci[i]);
}
fprintf(output, "\n");
return true;
}

View File

@ -9716,6 +9716,9 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal)
}
bool tableDone = reportLcpCompletion(lcpReport);
Uint32 started = lcpReport->maxGciStarted;
Uint32 completed = lcpReport->maxGciCompleted;
if(tableDone){
jam();
@ -9749,7 +9752,9 @@ void Dbdih::execLCP_FRAG_REP(Signal* signal)
signal->theData[1] = nodeId;
signal->theData[2] = tableId;
signal->theData[3] = fragId;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
signal->theData[4] = started;
signal->theData[5] = completed;
sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 6, JBB);
#endif
bool ok = false;
@ -10946,7 +10951,9 @@ void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr,
lcpNo = fmgReplicaPtr.p->nextLcp;
do {
ndbrequire(lcpNo < MAX_LCP_STORED);
if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID) {
if (fmgReplicaPtr.p->lcpStatus[lcpNo] == ZVALID &&
fmgReplicaPtr.p->maxGciStarted[lcpNo] <= coldgcp)
{
jam();
keepGci = fmgReplicaPtr.p->maxGciCompleted[lcpNo];
oldestRestorableGci = fmgReplicaPtr.p->maxGciStarted[lcpNo];
@ -10954,7 +10961,6 @@ void Dbdih::findMinGci(ReplicaRecordPtr fmgReplicaPtr,
return;
} else {
jam();
ndbrequire(fmgReplicaPtr.p->lcpStatus[lcpNo] == ZINVALID);
if (fmgReplicaPtr.p->createGci[0] == fmgReplicaPtr.p->initialGci) {
jam();
/*-------------------------------------------------------------------

View File

@ -134,7 +134,9 @@ bool PrepareOperationRecord::check() {
return true;
}
Uint32 PrepareOperationRecord::getLogRecordSize() {
Uint32 PrepareOperationRecord::getLogRecordSize(Uint32 wordsRead) {
if (wordsRead < 2)
return 2; // make sure we read more
return m_logRecordSize;
}

View File

@ -83,7 +83,7 @@ class PrepareOperationRecord {
friend NdbOut& operator<<(NdbOut&, const PrepareOperationRecord&);
public:
bool check();
Uint32 getLogRecordSize();
Uint32 getLogRecordSize(Uint32 wordsRead);
protected:
Uint32 m_recordType;

View File

@ -41,6 +41,7 @@ void doExit();
FILE * f= 0;
char fileName[256];
bool theDumpFlag = false;
bool thePrintFlag = true;
bool theCheckFlag = true;
bool onlyPageHeaders = false;
@ -208,7 +209,7 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read
case ZPREP_OP_TYPE:
poRecord = (PrepareOperationRecord *) redoLogPagePos;
wordIndex += poRecord->getLogRecordSize();
wordIndex += poRecord->getLogRecordSize(PAGESIZE-wordIndex);
if (wordIndex <= PAGESIZE) {
if (thePrintFlag) ndbout << (*poRecord);
if (theCheckFlag) {
@ -277,10 +278,9 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read
ndbout << " ------ERROR: UNKNOWN RECORD TYPE------" << endl;
// Print out remaining data in this page
for (int j = wordIndex; j < PAGESIZE; j++){
Uint32 unknown = redoLogPage[i*PAGESIZE + j];
ndbout_c("%-30d%-12u%-12x", j, unknown, unknown);
for (int k = wordIndex; k < PAGESIZE; k++){
Uint32 unknown = redoLogPage[i*PAGESIZE + k];
ndbout_c("%-30d%-12u%-12x", k, unknown, unknown);
}
doExit();
@ -289,8 +289,19 @@ NDB_COMMAND(redoLogFileReader, "redoLogFileReader", "redoLogFileReader", "Read
if (lastPage)
{
if (theDumpFlag)
{
ndbout << " ------PAGE END: DUMPING REST OF PAGE------" << endl;
for (int k = wordIndex > PAGESIZE ? oldWordIndex : wordIndex;
k < PAGESIZE; k++)
{
Uint32 word = redoLogPage[i*PAGESIZE + k];
ndbout_c("%-30d%-12u%-12x", k, word, word);
}
}
break;
}
if (wordIndex > PAGESIZE) {
words_from_previous_page = PAGESIZE - oldWordIndex;
ndbout << " ----------- Record continues on next page -----------" << endl;
@ -353,6 +364,8 @@ void readArguments(int argc, const char** argv)
{
if (strcmp(argv[i], "-noprint") == 0) {
thePrintFlag = false;
} else if (strcmp(argv[i], "-dump") == 0) {
theDumpFlag = true;
} else if (strcmp(argv[i], "-nocheck") == 0) {
theCheckFlag = false;
} else if (strcmp(argv[i], "-mbyteheaders") == 0) {

View File

@ -4454,7 +4454,7 @@ Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci)
*------------------------------------------------------------------------*/
tabortInd = ZFALSE;
setupFailData(signal);
if (tabortInd == ZFALSE) {
if (false && tabortInd == ZFALSE) {
jam();
commitGciHandling(signal, Tgci);
toCommitHandlingLab(signal);

View File

@ -60,7 +60,7 @@ int main(int argc, char** argv)
NDB_INIT(argv[0]);
// Print to stdout/console
g_eventLogger.createConsoleHandler();
g_eventLogger.setCategory("NDB");
g_eventLogger.setCategory("ndbd");
g_eventLogger.enable(Logger::LL_ON, Logger::LL_CRITICAL);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_ERROR);
g_eventLogger.enable(Logger::LL_ON, Logger::LL_WARNING);

View File

@ -30,13 +30,15 @@
#include <NodeState.hpp>
#include <NdbMem.h>
#include <NdbOut.hpp>
#include <NdbMutex.h>
#include <NdbSleep.h>
#include <EventLogger.hpp>
extern "C" {
extern void (* ndb_new_handler)();
}
extern EventLogger g_eventLogger;
/**
* Declare the global variables
@ -141,23 +143,23 @@ NdbShutdown(NdbShutdownType type,
switch(type){
case NST_Normal:
ndbout << "Shutdown initiated" << endl;
g_eventLogger.info("Shutdown initiated");
break;
case NST_Watchdog:
ndbout << "Watchdog " << shutting << " system" << endl;
g_eventLogger.info("Watchdog %s system", shutting);
break;
case NST_ErrorHandler:
ndbout << "Error handler " << shutting << " system" << endl;
g_eventLogger.info("Error handler %s system", shutting);
break;
case NST_ErrorHandlerSignal:
ndbout << "Error handler signal " << shutting << " system" << endl;
g_eventLogger.info("Error handler signal %s system", shutting);
break;
case NST_Restart:
ndbout << "Restarting system" << endl;
g_eventLogger.info("Restarting system");
break;
default:
ndbout << "Error handler " << shutting << " system"
<< " (unknown type: " << (unsigned)type << ")" << endl;
g_eventLogger.info("Error handler %s system (unknown type: %u)",
shutting, (unsigned)type);
type = NST_ErrorHandler;
break;
}
@ -173,7 +175,7 @@ NdbShutdown(NdbShutdownType type,
/**
* Very serious, don't attempt to free, just die!!
*/
ndbout << "Watchdog shutdown completed - " << exitAbort << endl;
g_eventLogger.info("Watchdog shutdown completed - %s", exitAbort);
#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
signal(6, SIG_DFL);
abort();
@ -227,7 +229,7 @@ NdbShutdown(NdbShutdownType type,
}
if(type != NST_Normal && type != NST_Restart){
ndbout << "Error handler shutdown completed - " << exitAbort << endl;
g_eventLogger.info("Error handler shutdown completed - %s", exitAbort);
#if ( defined VM_TRACE || defined ERROR_INSERT ) && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
signal(6, SIG_DFL);
abort();
@ -243,7 +245,7 @@ NdbShutdown(NdbShutdownType type,
exit(restartType);
}
ndbout << "Shutdown completed - exiting" << endl;
g_eventLogger.info("Shutdown completed - exiting");
} else {
/**
* Shutdown is already in progress
@ -253,7 +255,7 @@ NdbShutdown(NdbShutdownType type,
* If this is the watchdog, kill system the hard way
*/
if (type== NST_Watchdog){
ndbout << "Watchdog is killing system the hard way" << endl;
g_eventLogger.info("Watchdog is killing system the hard way");
#if defined VM_TRACE && ( ! ( defined NDB_OSE || defined NDB_SOFTOSE) )
signal(6, SIG_DFL);
abort();