Merge
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:
commit
f6c1d4191c
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
302
extra/innochecksum.c
Normal 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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
364
mysql-test/r/sp-dynamic.result
Normal file
364
mysql-test/r/sp-dynamic.result
Normal 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|
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
335
mysql-test/t/sp-dynamic.test
Normal file
335
mysql-test/t/sp-dynamic.test
Normal 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 ;|
|
@ -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...
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
#
|
||||
|
@ -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)
|
||||
#
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
||||
|
11
sql/item.cc
11
sql/item.cc
@ -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,
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -26,7 +26,6 @@ class JOIN;
|
||||
class select_subselect;
|
||||
class subselect_engine;
|
||||
class Item_bool_func2;
|
||||
class Item_arena;
|
||||
|
||||
/* base class for subselects */
|
||||
|
||||
|
@ -23,8 +23,6 @@
|
||||
|
||||
#include <my_tree.h>
|
||||
|
||||
class Item_arena;
|
||||
|
||||
class Item_sum :public Item_result_field
|
||||
{
|
||||
public:
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
147
sql/sp_head.cc
147
sql/sp_head.cc
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
232
sql/sql_parse.cc
232
sql/sql_parse.cc
@ -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
|
||||
|
1257
sql/sql_prepare.cc
1257
sql/sql_prepare.cc
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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)))))
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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> */
|
||||
|
10
sql/table.cc
10
sql/table.cc
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)));
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
// -------------------------------------------------------------------
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
/*-------------------------------------------------------------------
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user