mirror of
https://github.com/MariaDB/server.git
synced 2026-05-06 23:25:34 +02:00
Merge with 4.0.6
BitKeeper/etc/ignore: auto-union acinclude.m4: Auto merged configure.in: Auto merged heap/hp_delete.c: Auto merged heap/hp_scan.c: Auto merged include/my_base.h: Auto merged libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged myisam/mi_check.c: Auto merged myisam/mi_rnext_same.c: Auto merged myisam/sort.c: Auto merged mysql-test/r/alter_table.result: Auto merged mysql-test/r/distinct.result: Auto merged mysql-test/r/func_math.result: Auto merged mysql-test/r/group_by.result: Auto merged mysql-test/r/innodb.result: Auto merged mysql-test/r/select.result: Auto merged mysql-test/t/group_by.test: Auto merged mysql-test/t/select.test: Auto merged mysys/hash.c: Auto merged sql/field.h: Auto merged sql/field_conv.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/handler.cc: Auto merged sql/item_func.cc: Auto merged sql/item_func.h: Auto merged sql/log.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/opt_sum.cc: Auto merged sql/set_var.cc: Auto merged sql/set_var.h: Auto merged sql/sql_analyse.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_udf.cc: Auto merged sql/structs.h: Auto merged sql/uniques.cc: Auto merged strings/strto.c: Auto merged vio/vio.c: Auto merged BitKeeper/triggers/post-commit: Add changeset to commit messages sql-bench/crash-me.sh: Use version from 4.0 sql-bench/server-cfg.sh: Use version from 4.0
This commit is contained in:
commit
6d33f73416
88 changed files with 2090 additions and 1229 deletions
33
.bzrignore
33
.bzrignore
|
|
@ -75,6 +75,9 @@ Makefile.in'
|
|||
PENDING/*
|
||||
TAGS
|
||||
aclocal.m4
|
||||
autom4te-2.53.cache/output.0
|
||||
autom4te-2.53.cache/requests
|
||||
autom4te-2.53.cache/traces.0
|
||||
autom4te.cache/*
|
||||
autom4te.cache/output.0
|
||||
autom4te.cache/requests
|
||||
|
|
@ -123,6 +126,9 @@ bdb/db/crdel_auto.c
|
|||
bdb/db/db_auto.c
|
||||
bdb/dbinc_auto/*.*
|
||||
bdb/dbreg/dbreg_auto.c
|
||||
bdb/dist/autom4te-2.53.cache/output.0
|
||||
bdb/dist/autom4te-2.53.cache/requests
|
||||
bdb/dist/autom4te-2.53.cache/traces.0
|
||||
bdb/dist/autom4te.cache/*
|
||||
bdb/dist/autom4te.cache/output.0
|
||||
bdb/dist/autom4te.cache/requests
|
||||
|
|
@ -205,6 +211,14 @@ bdb/test/include.tcl
|
|||
bdb/test/logtrack.list
|
||||
bdb/txn/txn_auto.c
|
||||
binary/*
|
||||
bkpull.log
|
||||
bkpull.log.2
|
||||
bkpull.log.3
|
||||
bkpull.log.4
|
||||
bkpull.log.5
|
||||
bkpull.log.6
|
||||
bkpush.log
|
||||
build.log
|
||||
client/insert_test
|
||||
client/log_event.cc
|
||||
client/log_event.h
|
||||
|
|
@ -232,6 +246,7 @@ config.status
|
|||
configure
|
||||
configure.lineno
|
||||
core
|
||||
core.2430
|
||||
db-*.*.*
|
||||
dbug/user.t
|
||||
depcomp
|
||||
|
|
@ -249,6 +264,9 @@ include/my_config.h
|
|||
include/my_global.h
|
||||
include/mysql_version.h
|
||||
include/widec.h
|
||||
innobase/autom4te-2.53.cache/output.0
|
||||
innobase/autom4te-2.53.cache/requests
|
||||
innobase/autom4te-2.53.cache/traces.0
|
||||
innobase/autom4te.cache/*
|
||||
innobase/autom4te.cache/output.0
|
||||
innobase/autom4te.cache/requests
|
||||
|
|
@ -313,6 +331,7 @@ libmysqld/item_buff.cc
|
|||
libmysqld/item_cmpfunc.cc
|
||||
libmysqld/item_create.cc
|
||||
libmysqld/item_func.cc
|
||||
libmysqld/item_row.cc
|
||||
libmysqld/item_strfunc.cc
|
||||
libmysqld/item_sum.cc
|
||||
libmysqld/item_timefunc.cc
|
||||
|
|
@ -448,6 +467,7 @@ mysys/test_thr_alarm
|
|||
mysys/test_thr_lock
|
||||
mysys/test_vsnprintf
|
||||
mysys/testhash
|
||||
pull.log
|
||||
regex/re
|
||||
repl-tests/test-repl-ts/repl-timestamp.master.reject
|
||||
repl-tests/test-repl/foo-dump-slave.master.
|
||||
|
|
@ -515,6 +535,7 @@ sql/mysqld-purecov
|
|||
sql/mysqld-purify
|
||||
sql/mysqld-quantify
|
||||
sql/new.cc
|
||||
sql/safe_to_cache_query.txt
|
||||
sql/share/*.sys
|
||||
sql/share/charsets/gmon.out
|
||||
sql/share/gmon.out
|
||||
|
|
@ -524,6 +545,7 @@ sql/share/norwegian/errmsg.sys
|
|||
sql/sql_select.cc.orig
|
||||
sql/sql_yacc.cc
|
||||
sql/sql_yacc.h
|
||||
sql/sql_yacc.output
|
||||
sql/sql_yacc.yy.orig
|
||||
sql_error.cc
|
||||
sql_prepare.cc
|
||||
|
|
@ -557,14 +579,3 @@ vio/test-ssl
|
|||
vio/test-sslclient
|
||||
vio/test-sslserver
|
||||
vio/viotest-ssl
|
||||
bkpull.log
|
||||
bkpull.log.2
|
||||
bkpull.log.3
|
||||
build.log
|
||||
sql/safe_to_cache_query.txt
|
||||
bkpull.log.4
|
||||
bkpull.log.5
|
||||
bkpull.log.6
|
||||
bkpush.log
|
||||
sql/sql_yacc.output
|
||||
libmysqld/item_row.cc
|
||||
|
|
|
|||
|
|
@ -11,6 +11,6 @@ then
|
|||
(cd gemini && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
fi
|
||||
|
||||
CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wid-clash-51 -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
|
||||
CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa" CXX=gcc CXXFLAGS="-Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -O3 -fno-omit-frame-pointer -mcpu=v8 -Wa,-xarch=v8plusa -g" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client
|
||||
|
||||
gmake -j 4
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ aclocal && autoheader && aclocal && automake && autoconf
|
|||
(cd bdb/dist && sh s_all)
|
||||
(cd innobase && aclocal && autoheader && aclocal && automake && autoconf)
|
||||
|
||||
CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-function-dec -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -DHAVE_purify -DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-berkeley-db --with-innodb $EXTRA_CONFIG_FLAGS
|
||||
CFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wimplicit-int -Wparentheses -Wsign-compare -Wwrite-strings -Wunused -DHAVE_purify -DEXTRA_DEBUG -O2" CXX=gcc CXXLD=g++ CXXFLAGS="-g -Wimplicit -Wreturn-type -Wswitch -Wtrigraphs -Wcomment -W -Wchar-subscripts -Wformat -Wparentheses -Wsign-compare -Wwrite-strings -Woverloaded-virtual -Wsign-promo -Wreorder -Wctor-dtor-privacy -Wnon-virtual-dtor -felide-constructors -fno-exceptions -fno-rtti -DHAVE_purify -DEXTRA_DEBUG -O2" ./configure --prefix=/usr/local/mysql --enable-assembler --with-extra-charsets=complex --enable-thread-safe-client --with-berkeley-db --with-innodb $EXTRA_CONFIG_FLAGS
|
||||
|
||||
gmake -j 4
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ BK_STATUS=$BK_STATUS$BK_COMMIT
|
|||
if [ "$BK_STATUS" = OK ]
|
||||
then
|
||||
|
||||
CHANGESET=`bk -R prs -r+ -h -d':I:' ChangeSet`
|
||||
|
||||
#++
|
||||
# dev-public@
|
||||
#--
|
||||
|
|
@ -28,7 +30,7 @@ then
|
|||
List-ID: <bk.mysql-4.1>
|
||||
From: $FROM
|
||||
To: $TO
|
||||
Subject: bk commit - 4.1 tree
|
||||
Subject: bk commit - 4.1 tree ($CHANGESET)
|
||||
|
||||
EOF
|
||||
bk changes -v -r+
|
||||
|
|
@ -44,7 +46,7 @@ EOF
|
|||
List-ID: <bk.mysql-4.1>
|
||||
From: $FROM
|
||||
To: $INTERNALS
|
||||
Subject: bk commit into 4.1 tree
|
||||
Subject: bk commit into 4.1 tree ($CHANGESET)
|
||||
|
||||
Below is the list of changes that have just been committed into a local
|
||||
4.1 repository of $USER. When $USER does a push these changes will
|
||||
|
|
@ -71,7 +73,7 @@ EOF
|
|||
List-ID: <bk.mysql-4.1>
|
||||
From: $FROM
|
||||
To: $DOCS
|
||||
Subject: bk commit - 4.1 tree (Manual)
|
||||
Subject: bk commit - 4.1 tree (Manual) ($CHANGESET)
|
||||
|
||||
EOF
|
||||
bk changes -v -r+
|
||||
|
|
|
|||
36
acinclude.m4
36
acinclude.m4
|
|
@ -520,7 +520,8 @@ fi
|
|||
|
||||
AC_DEFUN(MYSQL_STACK_DIRECTION,
|
||||
[AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction,
|
||||
[AC_TRY_RUN([find_stack_direction ()
|
||||
[AC_TRY_RUN([#include <stdlib.h>
|
||||
int find_stack_direction ()
|
||||
{
|
||||
static char *addr = 0;
|
||||
auto char dummy;
|
||||
|
|
@ -532,7 +533,7 @@ AC_DEFUN(MYSQL_STACK_DIRECTION,
|
|||
else
|
||||
return (&dummy > addr) ? 1 : -1;
|
||||
}
|
||||
main ()
|
||||
int main ()
|
||||
{
|
||||
exit (find_stack_direction() < 0);
|
||||
}], ac_cv_c_stack_direction=1, ac_cv_c_stack_direction=-1,
|
||||
|
|
@ -1327,5 +1328,36 @@ AC_DEFUN(MYSQL_SYS_LARGEFILE,
|
|||
fi
|
||||
])
|
||||
|
||||
|
||||
# Local version of _AC_PROG_CXX_EXIT_DECLARATION that does not
|
||||
# include #stdlib.h as this breaks things on Solaris
|
||||
# (Conflicts with pthreads and big file handling)
|
||||
|
||||
m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
|
||||
[for ac_declaration in \
|
||||
''\
|
||||
'extern "C" void std::exit (int) throw (); using std::exit;' \
|
||||
'extern "C" void std::exit (int); using std::exit;' \
|
||||
'extern "C" void exit (int) throw ();' \
|
||||
'extern "C" void exit (int);' \
|
||||
'void exit (int);'
|
||||
do
|
||||
_AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
|
||||
$ac_declaration],
|
||||
[exit (42);])],
|
||||
[],
|
||||
[continue])
|
||||
_AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration],
|
||||
[exit (42);])],
|
||||
[break])
|
||||
done
|
||||
rm -f conftest*
|
||||
if test -n "$ac_declaration"; then
|
||||
echo '#ifdef __cplusplus' >>confdefs.h
|
||||
echo $ac_declaration >>confdefs.h
|
||||
echo '#endif' >>confdefs.h
|
||||
fi
|
||||
])# _AC_PROG_CXX_EXIT_DECLARATION
|
||||
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
125
client/errmsg.c
125
client/errmsg.c
|
|
@ -1,125 +0,0 @@
|
|||
/* Copyright (C) 2000 MySQL AB
|
||||
|
||||
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 */
|
||||
|
||||
/* Error messages for MySQL clients */
|
||||
/* error messages for the demon is in share/language/errmsg.sys */
|
||||
|
||||
#include <my_global.h>
|
||||
#include <my_sys.h>
|
||||
#include "errmsg.h"
|
||||
|
||||
#ifdef GERMAN
|
||||
const char *client_errors[]=
|
||||
{
|
||||
"Unbekannter MySQL Fehler",
|
||||
"Kann UNIX-Socket nicht anlegen (%d)",
|
||||
"Keine Verbindung zu lokalem MySQL Server, socket: '%-.64s' (%d)",
|
||||
"Keine Verbindung zu MySQL Server auf %-.64s (%d)",
|
||||
"Kann TCP/IP-Socket nicht anlegen (%d)",
|
||||
"Unbekannter MySQL Server Host (%-.64s) (%d)",
|
||||
"MySQL Server nicht vorhanden",
|
||||
"Protokolle ungleich. Server Version = % d Client Version = %d",
|
||||
"MySQL client got out of memory",
|
||||
"Wrong host info",
|
||||
"Localhost via UNIX socket",
|
||||
"%-.64s via TCP/IP",
|
||||
"Error in server handshake",
|
||||
"Lost connection to MySQL server during query",
|
||||
"Commands out of sync; You can't run this command now",
|
||||
"Verbindung ueber Named Pipe; Host: %-.64s",
|
||||
"Kann nicht auf Named Pipe warten. Host: %-.64s pipe: %-.32s (%lu)",
|
||||
"Kann Named Pipe nicht oeffnen. Host: %-.64s pipe: %-.32s (%lu)",
|
||||
"Kann den Status der Named Pipe nicht setzen. Host: %-.64s pipe: %-.32s (%lu)",
|
||||
"Can't initialize character set %-.64s (path: %-.64s)",
|
||||
"Got packet bigger than 'max_allowed_packet'",
|
||||
"Embedded server",
|
||||
"Error on SHOW SLAVE STATUS:",
|
||||
"Error on SHOW SLAVE HOSTS:",
|
||||
"Error connecting to slave:",
|
||||
"Error connecting to master:"
|
||||
|
||||
};
|
||||
|
||||
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
|
||||
|
||||
#elif defined PORTUGUESE
|
||||
const char *client_errors[]=
|
||||
{
|
||||
"Erro desconhecido do MySQL",
|
||||
"Não pode criar 'UNIX socket' (%d)",
|
||||
"Não pode se conectar ao servidor MySQL local através do 'socket' '%-.64s' (%d)",
|
||||
"Não pode se conectar ao servidor MySQL em '%-.64s' (%d)",
|
||||
"Não pode criar 'socket TCP/IP' (%d)",
|
||||
"'Host' servidor MySQL '%-.64s' (%d) desconhecido",
|
||||
"Servidor MySQL desapareceu",
|
||||
"Incompatibilidade de protocolos. Versão do Servidor: %d - Versão do Cliente: %d",
|
||||
"Cliente do MySQL com falta de memória",
|
||||
"Informação inválida de 'host'",
|
||||
"Localhost via 'UNIX socket'",
|
||||
"%-.64s via 'TCP/IP'",
|
||||
"Erro na negociação de acesso ao servidor",
|
||||
"Conexão perdida com servidor MySQL durante 'query'",
|
||||
"Comandos fora de sincronismo. Você não pode executar este comando agora",
|
||||
"%-.64s via 'named pipe'",
|
||||
"Não pode esperar pelo 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
|
||||
"Não pode abrir 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
|
||||
"Não pode estabelecer o estado do 'named pipe' para o 'host' %-.64s - 'pipe' %-.32s (%lu)",
|
||||
"Não pode inicializar conjunto de caracteres %-.64s (caminho %-.64s)",
|
||||
"Obteve pacote maior do que 'max_allowed_packet'",
|
||||
"Embedded server",
|
||||
"Error on SHOW SLAVE STATUS:",
|
||||
"Error on SHOW SLAVE HOSTS:",
|
||||
"Error connecting to slave:",
|
||||
"Error connecting to master:"
|
||||
};
|
||||
|
||||
#else /* ENGLISH */
|
||||
const char *client_errors[]=
|
||||
{
|
||||
"Unknown MySQL error",
|
||||
"Can't create UNIX socket (%d)",
|
||||
"Can't connect to local MySQL server through socket '%-.64s' (%d)",
|
||||
"Can't connect to MySQL server on '%-.64s' (%d)",
|
||||
"Can't create TCP/IP socket (%d)",
|
||||
"Unknown MySQL Server Host '%-.64s' (%d)",
|
||||
"MySQL server has gone away",
|
||||
"Protocol mismatch. Server Version = %d Client Version = %d",
|
||||
"MySQL client run out of memory",
|
||||
"Wrong host info",
|
||||
"Localhost via UNIX socket",
|
||||
"%-.64s via TCP/IP",
|
||||
"Error in server handshake",
|
||||
"Lost connection to MySQL server during query",
|
||||
"Commands out of sync; You can't run this command now",
|
||||
"%-.64s via named pipe",
|
||||
"Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)",
|
||||
"Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)",
|
||||
"Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)",
|
||||
"Can't initialize character set %-.64s (path: %-.64s)",
|
||||
"Got packet bigger than 'max_allowed_packet'",
|
||||
"Embedded server",
|
||||
"Error on SHOW SLAVE STATUS:",
|
||||
"Error on SHOW SLAVE HOSTS:",
|
||||
"Error connecting to slave:",
|
||||
"Error connecting to master:"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
void init_client_errs(void)
|
||||
{
|
||||
my_errmsg[CLIENT_ERRMAP] = &client_errors[0];
|
||||
}
|
||||
|
|
@ -20,19 +20,34 @@
|
|||
|
||||
static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
|
||||
ulong blength, my_bool print_status);
|
||||
static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
|
||||
my_bool print_status);
|
||||
|
||||
/* Returns 0 if the HEAP is ok */
|
||||
|
||||
/*
|
||||
Check if keys and rows are ok in a heap table
|
||||
|
||||
SYNOPSIS
|
||||
heap_check_heap()
|
||||
info Table handler
|
||||
print_status Prints some extra status
|
||||
|
||||
NOTES
|
||||
Doesn't change the state of the table handler
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
|
||||
int heap_check_heap(HP_INFO *info, my_bool print_status)
|
||||
{
|
||||
int error;
|
||||
uint key;
|
||||
ulong records=0, deleted=0, pos, next_block;
|
||||
HP_SHARE *share=info->s;
|
||||
DBUG_ENTER("heap_check_keys");
|
||||
HP_INFO save_info= *info; /* Needed because scan_init */
|
||||
DBUG_ENTER("heap_check_heap");
|
||||
|
||||
for (error=key=0 ; key < share->keys ; key++)
|
||||
for (error=key= 0 ; key < share->keys ; key++)
|
||||
{
|
||||
if (share->keydef[key].algorithm == HA_KEY_ALG_BTREE)
|
||||
error|= check_one_rb_key(info, key, share->records, print_status);
|
||||
|
|
@ -40,7 +55,41 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
|
|||
error|= check_one_key(share->keydef + key, key, share->records,
|
||||
share->blength, print_status);
|
||||
}
|
||||
/*
|
||||
This is basicly the same code as in hp_scan, but we repeat it here to
|
||||
get shorter DBUG log file.
|
||||
*/
|
||||
for (pos=next_block= 0 ; ; pos++)
|
||||
{
|
||||
if (pos < next_block)
|
||||
{
|
||||
info->current_ptr+= share->block.recbuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_block+= share->block.records_in_block;
|
||||
if (next_block >= share->records+share->deleted)
|
||||
{
|
||||
next_block= share->records+share->deleted;
|
||||
if (pos >= next_block)
|
||||
break; /* End of file */
|
||||
}
|
||||
}
|
||||
_hp_find_record(info,pos);
|
||||
|
||||
if (!info->current_ptr[share->reclength])
|
||||
deleted++;
|
||||
else
|
||||
records++;
|
||||
}
|
||||
|
||||
if (records != share->records || deleted != share->deleted)
|
||||
{
|
||||
DBUG_PRINT("error",("Found rows: %lu (%lu) deleted %lu (%lu)",
|
||||
records, share->records, deleted, share->deleted));
|
||||
error= 1;
|
||||
}
|
||||
*info= save_info;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ int heap_delete(HP_INFO *info, const byte *record)
|
|||
pos[share->reclength]=0; /* Record deleted */
|
||||
share->deleted++;
|
||||
info->current_hash_ptr=0;
|
||||
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
|
||||
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(0);
|
||||
err:
|
||||
if (++(share->records) == share->blength)
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ int heap_scan(register HP_INFO *info, byte *record)
|
|||
}
|
||||
if (!info->current_ptr[share->reclength])
|
||||
{
|
||||
DBUG_PRINT("warning",("Found deleted record"));
|
||||
info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
|
||||
DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,10 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
|
|||
|
||||
memcpy(pos,heap_new,(size_t) share->reclength);
|
||||
if (++(share->records) == share->blength) share->blength+= share->blength;
|
||||
|
||||
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
|
||||
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
|
||||
#endif
|
||||
if (auto_key_changed)
|
||||
heap_update_auto_increment(info, heap_new);
|
||||
DBUG_RETURN(0);
|
||||
|
|
|
|||
|
|
@ -61,9 +61,13 @@ int heap_write(HP_INFO *info, const byte *record)
|
|||
info->current_ptr=pos;
|
||||
info->current_hash_ptr=0;
|
||||
info->update|=HA_STATE_AKTIV;
|
||||
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)
|
||||
DBUG_EXECUTE("check_heap",heap_check_heap(info, 0););
|
||||
#endif
|
||||
if (share->auto_key)
|
||||
heap_update_auto_increment(info, record);
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
|
||||
info->errkey= keydef - share->keydef;
|
||||
|
|
@ -83,6 +87,7 @@ err:
|
|||
*((byte**) pos)=share->del_link;
|
||||
share->del_link=pos;
|
||||
pos[share->reclength]=0; /* Record deleted */
|
||||
|
||||
DBUG_RETURN(my_errno);
|
||||
} /* heap_write */
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ extern const char *client_errors[]; /* Error messages */
|
|||
|
||||
#define CR_MIN_ERROR 2000 /* For easier client code */
|
||||
#define CR_MAX_ERROR 2999
|
||||
#if defined(OS2) && defined( MYSQL_SERVER)
|
||||
#if defined(OS2) && defined(MYSQL_SERVER)
|
||||
#define CER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
#else
|
||||
#define ER(X) client_errors[(X)-CR_MIN_ERROR]
|
||||
|
|
@ -62,9 +62,9 @@ extern const char *client_errors[]; /* Error messages */
|
|||
#define CR_PROBE_SLAVE_CONNECT 2024
|
||||
#define CR_PROBE_MASTER_CONNECT 2025
|
||||
#define CR_SSL_CONNECTION_ERROR 2026
|
||||
#define CR_MALFORMED_PACKET 2027
|
||||
|
||||
/* new 4.1 error codes */
|
||||
#define CR_INVALID_CONN_HANDLE 2027
|
||||
#define CR_NULL_POINTER 2028
|
||||
#define CR_NO_PREPARE_STMT 2029
|
||||
#define CR_NOT_ALL_PARAMS_BOUND 2030
|
||||
|
|
@ -85,3 +85,4 @@ extern const char *client_errors[]; /* Error messages */
|
|||
#define CR_SHARED_MEMORY_CONNECT_ABANDODED_ERROR 2044
|
||||
#define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2045
|
||||
#define CR_CONN_UNKNOW_PROTOCOL 2046
|
||||
#define CR_INVALID_CONN_HANDLE 2047
|
||||
|
|
|
|||
|
|
@ -110,7 +110,8 @@ enum ha_extra_function {
|
|||
HA_EXTRA_BULK_INSERT_BEGIN,
|
||||
HA_EXTRA_BULK_INSERT_FLUSH, /* Flush one index */
|
||||
HA_EXTRA_BULK_INSERT_END,
|
||||
HA_EXTRA_PREPARE_FOR_DELETE
|
||||
HA_EXTRA_PREPARE_FOR_DELETE,
|
||||
HA_EXTRA_PREPARE_FOR_UPDATE /* Remove read cache if problems */
|
||||
};
|
||||
|
||||
/* The following is parameter to ha_panic() */
|
||||
|
|
|
|||
|
|
@ -2702,14 +2702,22 @@ row_search_for_mysql(
|
|||
|
||||
unique_search_from_clust_index = TRUE;
|
||||
|
||||
if (prebuilt->select_lock_type == LOCK_NONE
|
||||
if (trx->mysql_n_tables_locked == 0
|
||||
&& prebuilt->select_lock_type == LOCK_NONE
|
||||
&& trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
|
||||
&& trx->read_view) {
|
||||
|
||||
/* This is a SELECT query done as a consistent read,
|
||||
and the read view has already been allocated:
|
||||
let us try a search shortcut through the hash
|
||||
index */
|
||||
index.
|
||||
NOTE that we must also test that
|
||||
mysql_n_tables_locked == 0, because this might
|
||||
also be INSERT INTO ... SELECT ... or
|
||||
CREATE TABLE ... SELECT ... . Our algorithm is
|
||||
NOT prepared to inserts interleaved with the SELECT,
|
||||
and if we try that, we can deadlock on the adaptive
|
||||
hash index semaphore! */
|
||||
|
||||
if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
|
||||
/* There is an x-latch request: release
|
||||
|
|
|
|||
|
|
@ -123,6 +123,7 @@ int nisam_extra(N_INFO *info, enum ha_extra_function function)
|
|||
}
|
||||
#endif
|
||||
if (!(info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)))
|
||||
{
|
||||
if (!(init_io_cache(&info->rec_cache,info->dfile,0,
|
||||
WRITE_CACHE,info->s->state.data_file_length,
|
||||
(pbool) (info->lock_type != F_UNLCK),
|
||||
|
|
@ -131,7 +132,12 @@ int nisam_extra(N_INFO *info, enum ha_extra_function function)
|
|||
info->opt_flag|=WRITE_CACHE_USED;
|
||||
info->update&= ~HA_STATE_ROW_CHANGED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case HA_EXTRA_PREPARE_FOR_UPDATE:
|
||||
if (info->s->data_file_type != DYNAMIC_RECORD)
|
||||
break;
|
||||
/* Remove read/write cache if dynamic rows */
|
||||
case HA_EXTRA_NO_CACHE:
|
||||
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ const char *client_errors[]=
|
|||
"Error connecting to slave:",
|
||||
"Error connecting to master:",
|
||||
"SSL connection error",
|
||||
"Invalid connection handle",
|
||||
"Malformed packet",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
|
|
@ -70,7 +70,8 @@ const char *client_errors[]=
|
|||
"Can't open shared memory. %s event don't create for client (%lu)",
|
||||
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
|
||||
"Can't open shared memory. Can't send the request event to server (%lu)",
|
||||
"Wrong or unknown protocol"
|
||||
"Wrong or unknown protocol",
|
||||
"Invalid connection handle"
|
||||
};
|
||||
|
||||
/* Start of code added by Roberto M. Serqueira - martinsc@uol.com.br - 05.24.2001 */
|
||||
|
|
@ -105,7 +106,7 @@ const char *client_errors[]=
|
|||
"Error connecting to slave:",
|
||||
"Error connecting to master:",
|
||||
"SSL connection error",
|
||||
"Invalid connection handle",
|
||||
"Malformed packet",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
|
|
@ -124,7 +125,8 @@ const char *client_errors[]=
|
|||
"Can't open shared memory. %s event don't create for client (%lu)",
|
||||
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
|
||||
"Can't open shared memory. Can't send the request event to server (%lu)",
|
||||
"Wrong or unknown protocol"
|
||||
"Wrong or unknown protocol",
|
||||
"Invalid connection handle"
|
||||
};
|
||||
|
||||
#else /* ENGLISH */
|
||||
|
|
@ -157,7 +159,7 @@ const char *client_errors[]=
|
|||
"Error connecting to slave:",
|
||||
"Error connecting to master:",
|
||||
"SSL connection error",
|
||||
"Invalid connection handle",
|
||||
"Malformed packet",
|
||||
"Invalid use of null pointer",
|
||||
"Statement not prepared",
|
||||
"Not all parameters data supplied",
|
||||
|
|
@ -176,7 +178,8 @@ const char *client_errors[]=
|
|||
"Can't open shared memory. %s event don't create for client (%lu)",
|
||||
"Can't open shared memory. Server abandoded and don't sent the answer event (%lu)",
|
||||
"Can't open shared memory. Can't send the request event to server (%lu)",
|
||||
"Wrong or unknown protocol"
|
||||
"Wrong or unknown protocol",
|
||||
"Invalid connection handle"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1196,7 +1196,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
|||
ulong pkt_len;
|
||||
ulong len;
|
||||
uchar *cp;
|
||||
char *to;
|
||||
char *to, *end_to;
|
||||
MYSQL_DATA *result;
|
||||
MYSQL_ROWS **prev_ptr,*cur;
|
||||
NET *net = &mysql->net;
|
||||
|
|
@ -1242,6 +1242,7 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
|||
*prev_ptr=cur;
|
||||
prev_ptr= &cur->next;
|
||||
to= (char*) (cur->data+fields+1);
|
||||
end_to=to+pkt_len-1;
|
||||
for (field=0 ; field < fields ; field++)
|
||||
{
|
||||
if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
|
||||
|
|
@ -1251,6 +1252,13 @@ static MYSQL_DATA *read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
|
|||
else
|
||||
{
|
||||
cur->data[field] = to;
|
||||
if (to+len > end_to)
|
||||
{
|
||||
free_rows(result);
|
||||
net->last_errno=CR_MALFORMED_PACKET;
|
||||
strmov(net->last_error,ER(net->last_errno));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
memcpy(to,(char*) cp,len); to[len]=0;
|
||||
to+=len+1;
|
||||
cp+=len;
|
||||
|
|
|
|||
|
|
@ -274,11 +274,39 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Make a copy of array and the strings array points to
|
||||
*/
|
||||
|
||||
char **copy_arguments(int argc, char **argv)
|
||||
{
|
||||
uint length= 0;
|
||||
char **from, **res, **end= argv+argc;
|
||||
|
||||
for (from=argv ; from != end ; from++)
|
||||
length+= strlen(*from);
|
||||
|
||||
if ((res= (char**) my_malloc(sizeof(argv)*(argc+1)+length+argc,
|
||||
MYF(MY_WME))))
|
||||
{
|
||||
char **to= res, *to_str= (char*) (res+argc+1);
|
||||
for (from=argv ; from != end ;)
|
||||
{
|
||||
*to++= to_str;
|
||||
to_str= strmov(to_str, *from++)+1;
|
||||
}
|
||||
*to= 0; // Last ptr should be null
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
static my_bool inited, org_my_init_done;
|
||||
ulong max_allowed_packet, net_buffer_length;
|
||||
char ** copy_arguments_ptr= 0;
|
||||
|
||||
int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
||||
{
|
||||
|
|
@ -318,6 +346,14 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
MY_INIT((char *)"mysql_embedded"); // init my_sys library & pthreads
|
||||
}
|
||||
|
||||
/*
|
||||
Make a copy of the arguments to guard against applications that
|
||||
may change or move the initial arguments.
|
||||
*/
|
||||
if (argvp == &argv)
|
||||
if (!(copy_arguments_ptr= argv= copy_arguments(argc, argv)))
|
||||
return 1;
|
||||
|
||||
tzset(); // Set tzname
|
||||
|
||||
start_time=time((time_t*) 0);
|
||||
|
|
@ -565,6 +601,8 @@ int STDCALL mysql_server_init(int argc, char **argv, char **groups)
|
|||
|
||||
void STDCALL mysql_server_end()
|
||||
{
|
||||
my_free((char*) copy_arguments_ptr, MYF(MY_ALLOW_ZERO_PTR));
|
||||
copy_arguments_ptr=0;
|
||||
clean_up(0);
|
||||
#ifdef THREAD
|
||||
/* Don't call my_thread_end() if the application is using MY_INIT() */
|
||||
|
|
|
|||
|
|
@ -2329,13 +2329,13 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
|
|||
for (i=0 ; i < sort_info.total_keys ; i++)
|
||||
{
|
||||
sort_param[i].read_cache=param->read_cache;
|
||||
sort_param[i].sortbuff_size=
|
||||
/*
|
||||
two approaches: the same amount of memory for each thread
|
||||
or the memory for the same number of keys for each thread...
|
||||
In the second one all the threads will fill their sort_buffers
|
||||
(and call write_keys) at the same time, putting more stress on i/o.
|
||||
*/
|
||||
sort_param[i].sortbuff_size=
|
||||
#ifndef USING_SECOND_APPROACH
|
||||
param->sort_buffer_length/sort_info.total_keys;
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -165,6 +165,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
|
|||
HA_STATE_EXTEND_BLOCK);
|
||||
}
|
||||
break;
|
||||
case HA_EXTRA_PREPARE_FOR_UPDATE:
|
||||
if (info->s->data_file_type != DYNAMIC_RECORD)
|
||||
break;
|
||||
/* Remove read/write cache if dynamic rows */
|
||||
case HA_EXTRA_NO_CACHE:
|
||||
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,14 +28,13 @@
|
|||
int mi_rnext_same(MI_INFO *info, byte *buf)
|
||||
{
|
||||
int error;
|
||||
uint inx,flag,not_used;
|
||||
uint inx,not_used;
|
||||
MI_KEYDEF *keyinfo;
|
||||
DBUG_ENTER("mi_rnext_same");
|
||||
|
||||
if ((int) (inx=info->lastinx) < 0 || info->lastpos == HA_OFFSET_ERROR)
|
||||
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
|
||||
keyinfo=info->s->keyinfo+inx;
|
||||
flag=SEARCH_BIGGER; /* Read next */
|
||||
if (fast_mi_readinfo(info))
|
||||
DBUG_RETURN(my_errno);
|
||||
|
||||
|
|
@ -57,7 +56,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
|
|||
for (;;)
|
||||
{
|
||||
if ((error=_mi_search_next(info,keyinfo,info->lastkey,
|
||||
info->lastkey_length,flag,
|
||||
info->lastkey_length,SEARCH_BIGGER,
|
||||
info->s->state.key_root[inx])))
|
||||
break;
|
||||
if (ha_key_cmp(keyinfo->seg,info->lastkey2,info->lastkey,
|
||||
|
|
|
|||
|
|
@ -376,7 +376,6 @@ pthread_handler_decl(thr_find_all_keys,arg)
|
|||
mi_check_print_error(info->sort_info->param,"Sort buffer to small"); /* purecov: tested */
|
||||
goto err; /* purecov: tested */
|
||||
}
|
||||
// (*info->lock_in_memory)(info->sort_info->param);/* Everything is allocated */
|
||||
|
||||
if (info->sort_info->param->testflag & T_VERBOSE)
|
||||
printf("Key %d - Allocating buffer for %d keys\n",info->key+1,keys);
|
||||
|
|
@ -456,9 +455,9 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
|
|||
byte *mergebuf=0;
|
||||
LINT_INIT(length);
|
||||
|
||||
for (i=0, sinfo=sort_param ; i<sort_info->total_keys ; i++,
|
||||
rec_per_key_part+=sinfo->keyinfo->keysegs,
|
||||
sinfo++)
|
||||
for (i= 0, sinfo= sort_param ;
|
||||
i < sort_info->total_keys ;
|
||||
i++, rec_per_key_part+=sinfo->keyinfo->keysegs, sinfo++)
|
||||
{
|
||||
if (!sinfo->sort_keys)
|
||||
{
|
||||
|
|
@ -484,11 +483,14 @@ int thr_write_keys(MI_SORT_PARAM *sort_param)
|
|||
}
|
||||
}
|
||||
my_free((gptr) sinfo->sort_keys,MYF(0));
|
||||
my_free(mi_get_rec_buff_ptr(info, sinfo->rec_buff), MYF(MY_ALLOW_ZERO_PTR));
|
||||
my_free(mi_get_rec_buff_ptr(info, sinfo->rec_buff),
|
||||
MYF(MY_ALLOW_ZERO_PTR));
|
||||
sinfo->sort_keys=0;
|
||||
}
|
||||
|
||||
for (i=0, sinfo=sort_param ; i<sort_info->total_keys ; i++,
|
||||
for (i= 0, sinfo= sort_param ;
|
||||
i < sort_info->total_keys ;
|
||||
i++,
|
||||
delete_dynamic(&sinfo->buffpek),
|
||||
close_cached_file(&sinfo->tempfile),
|
||||
close_cached_file(&sinfo->tempfile_for_exceptions),
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ int myrg_extra(MYRG_INFO *info,enum ha_extra_function function,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (function == HA_EXTRA_NO_CACHE || function == HA_EXTRA_RESET)
|
||||
if (function == HA_EXTRA_NO_CACHE || function == HA_EXTRA_RESET ||
|
||||
function == HA_EXTRA_PREPARE_FOR_UPDATE)
|
||||
info->cache_in_use=0;
|
||||
if (function == HA_EXTRA_RESET || function == HA_EXTRA_RESET_STATE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -47,13 +47,17 @@ which ()
|
|||
|
||||
sleep_until_file_deleted ()
|
||||
{
|
||||
file=$1
|
||||
pid=$1;
|
||||
file=$2
|
||||
loop=$SLEEP_TIME_FOR_DELETE
|
||||
while (test $loop -gt 0)
|
||||
do
|
||||
if [ ! -r $file ]
|
||||
then
|
||||
sleep $SLEEP_TIME_AFTER_RESTART
|
||||
if test $pid != "0"
|
||||
then
|
||||
wait_for_pid $pid
|
||||
fi
|
||||
return
|
||||
fi
|
||||
sleep 1
|
||||
|
|
@ -79,6 +83,13 @@ sleep_until_file_created ()
|
|||
exit 1;
|
||||
}
|
||||
|
||||
# For the future
|
||||
|
||||
wait_for_pid()
|
||||
{
|
||||
pid=$1
|
||||
}
|
||||
|
||||
# No paths below as we can't be sure where the program is!
|
||||
|
||||
SED=sed
|
||||
|
|
@ -152,6 +163,7 @@ TOT_TEST=0
|
|||
USERT=0
|
||||
SYST=0
|
||||
REALT=0
|
||||
FAST_START=""
|
||||
MYSQL_TMP_DIR=$MYSQL_TEST_DIR/var/tmp
|
||||
SLAVE_LOAD_TMPDIR=../../var/tmp #needs to be same length to test logging
|
||||
RES_SPACE=" "
|
||||
|
|
@ -319,7 +331,7 @@ while test $# -gt 0; do
|
|||
VALGRIND="valgrind --alignment=8 --leak-check=yes"
|
||||
EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc"
|
||||
EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc"
|
||||
SLEEP_TIME_AFTER_RESTART=60
|
||||
#SLEEP_TIME_AFTER_RESTART=120
|
||||
SLEEP_TIME_FOR_DELETE=60
|
||||
;;
|
||||
--valgrind-options=*)
|
||||
|
|
@ -340,6 +352,9 @@ while test $# -gt 0; do
|
|||
--debug=d:t:i:O,$MYSQL_TEST_DIR/var/log/slave.trace"
|
||||
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT --debug"
|
||||
;;
|
||||
--fast)
|
||||
FAST_START=1
|
||||
;;
|
||||
-- ) shift; break ;;
|
||||
--* ) $ECHO "Unrecognized option: $1"; exit 1 ;;
|
||||
* ) break ;;
|
||||
|
|
@ -736,12 +751,19 @@ EOF
|
|||
|
||||
manager_term()
|
||||
{
|
||||
ident=$1
|
||||
pid=$1
|
||||
ident=$2
|
||||
shift
|
||||
if [ $USE_MANAGER = 0 ] ; then
|
||||
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock -O \
|
||||
connect_timeout=5 -O shutdown_timeout=20 shutdown >> $MYSQL_MANAGER_LOG 2>&1
|
||||
return
|
||||
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=5 --shutdown_timeout=20 shutdown >> $MYSQL_MANAGER_LOG 2>&1
|
||||
res=$?
|
||||
# Some systems require an extra connect
|
||||
$MYSQLADMIN --no-defaults -uroot --socket=$MYSQL_TMP_DIR/$ident.sock --connect_timeout=1 ping >> $MYSQL_MANAGER_LOG 2>&1
|
||||
if test $res = 0
|
||||
then
|
||||
wait_for_pid $pid
|
||||
fi
|
||||
return $res
|
||||
fi
|
||||
$MYSQL_MANAGER_CLIENT $MANAGER_QUIET_OPT --user=$MYSQL_MANAGER_USER \
|
||||
--password=$MYSQL_MANAGER_PW --port=$MYSQL_MANAGER_PORT <<EOF
|
||||
|
|
@ -983,12 +1005,13 @@ stop_slave ()
|
|||
fi
|
||||
if [ x$this_slave_running = x1 ]
|
||||
then
|
||||
manager_term $slave_ident
|
||||
pid=`$CAT $slave_pid`
|
||||
manager_term $pid $slave_ident
|
||||
if [ $? != 0 ] && [ -f $slave_pid ]
|
||||
then # try harder!
|
||||
$ECHO "slave not cooperating with mysqladmin, will try manual kill"
|
||||
kill `$CAT $slave_pid`
|
||||
sleep_until_file_deleted $slave_pid
|
||||
kill $pid
|
||||
sleep_until_file_deleted $pid $slave_pid
|
||||
if [ -f $slave_pid ] ; then
|
||||
$ECHO "slave refused to die. Sending SIGKILL"
|
||||
kill -9 `$CAT $slave_pid`
|
||||
|
|
@ -1007,12 +1030,13 @@ stop_master ()
|
|||
{
|
||||
if [ x$MASTER_RUNNING = x1 ]
|
||||
then
|
||||
manager_term master
|
||||
pid=`$CAT $MASTER_MYPID`
|
||||
manager_term $pid master
|
||||
if [ $? != 0 ] && [ -f $MASTER_MYPID ]
|
||||
then # try harder!
|
||||
$ECHO "master not cooperating with mysqladmin, will try manual kill"
|
||||
kill `$CAT $MASTER_MYPID`
|
||||
sleep_until_file_deleted $MASTER_MYPID
|
||||
kill $pid
|
||||
sleep_until_file_deleted $pid $MASTER_MYPID
|
||||
if [ -f $MASTER_MYPID ] ; then
|
||||
$ECHO "master refused to die. Sending SIGKILL"
|
||||
kill -9 `$CAT $MASTER_MYPID`
|
||||
|
|
@ -1233,14 +1257,19 @@ run_testcase ()
|
|||
|
||||
if [ -z "$USE_RUNNING_SERVER" ]
|
||||
then
|
||||
if [ -z "$FAST_START" ]
|
||||
then
|
||||
# Ensure that no old mysqld test servers are running
|
||||
$MYSQLADMIN --no-defaults --socket=$MASTER_MYSOCK -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
|
||||
$MYSQLADMIN --no-defaults --socket=$SLAVE_MYSOCK -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
|
||||
$MYSQLADMIN --no-defaults --host=$hostname --port=$MASTER_MYPORT -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
|
||||
$MYSQLADMIN --no-defaults --host=$hostname --port=$SLAVE_MYPORT -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
|
||||
$MYSQLADMIN --no-defaults --host=$hostname --port=`expr $SLAVE_MYPORT + 1` -u root -O connect_timeout=5 -O shutdown_timeout=20 shutdown > /dev/null 2>&1
|
||||
sleep_until_file_deleted $MASTER_MYPID
|
||||
sleep_until_file_deleted $SLAVE_MYPID
|
||||
sleep_until_file_deleted 0 $MASTER_MYPID
|
||||
sleep_until_file_deleted 0 $SLAVE_MYPID
|
||||
else
|
||||
rm $MASTER_MYPID $SLAVE_MYPID
|
||||
fi
|
||||
|
||||
# Kill any running managers
|
||||
if [ -f "$MANAGER_PID_FILE" ]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
drop table if exists t1;
|
||||
drop table if exists t1,t2;
|
||||
create table t1 (
|
||||
col1 int not null auto_increment primary key,
|
||||
col2 varchar(30) not null,
|
||||
|
|
|
|||
|
|
@ -198,6 +198,30 @@ a
|
|||
select distinct 1 from t1,t3 where t1.a=t3.a;
|
||||
1
|
||||
1
|
||||
explain SELECT distinct t1.a from t1;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 index NULL PRIMARY 4 NULL 2 Using index
|
||||
explain SELECT distinct t1.a from t1 order by a desc;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 index NULL PRIMARY 4 NULL 2 Using index
|
||||
explain SELECT t1.a from t1 group by a order by a desc;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 index NULL PRIMARY 4 NULL 2 Using index
|
||||
explain SELECT distinct t1.a from t1 order by a desc limit 1;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t1 index NULL PRIMARY 4 NULL 2 Using index
|
||||
explain SELECT distinct a from t3 order by a desc limit 2;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t3 index NULL a 5 NULL 204 Using index
|
||||
explain SELECT distinct a,b from t3 order by a+1;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
|
||||
explain SELECT distinct a,b from t3 order by a limit 10;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t3 index NULL a 5 NULL 204 Using temporary
|
||||
explain SELECT a,b from t3 group by a,b order by a+1;
|
||||
table type possible_keys key key_len ref rows Extra
|
||||
t3 ALL NULL NULL NULL NULL 204 Using temporary; Using filesort
|
||||
drop table t1,t2,t3,t4;
|
||||
CREATE TABLE t1 (name varchar(255));
|
||||
INSERT INTO t1 VALUES ('aa'),('ab'),('ac'),('ad'),('ae');
|
||||
|
|
|
|||
|
|
@ -31,9 +31,10 @@ log10(100) log10(18) log10(-4) log10(0) log10(NULL)
|
|||
select pow(10,log10(10)),power(2,4);
|
||||
pow(10,log10(10)) power(2,4)
|
||||
10.000000 16.000000
|
||||
set @@rand_seed1=10000000,@@rand_seed2=1000000;
|
||||
select rand(999999),rand();
|
||||
rand(999999) rand()
|
||||
0.014231365187309 0.8078568166195
|
||||
0.014231365187309 0.028870999839968
|
||||
select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1);
|
||||
PI() sin(pi()/2) cos(pi()/2) abs(tan(pi())) cot(1) asin(1) acos(0) atan(1)
|
||||
3.141593 1.000000 0.000000 0.000000 0.64209262 1.570796 1.570796 0.785398
|
||||
|
|
|
|||
|
|
@ -207,6 +207,14 @@ Documentation 0
|
|||
Host communication 0
|
||||
kkkkkkkkkkk lllllllllll 3
|
||||
Test Procedures 0
|
||||
select value,description,COUNT(bug_id) from t2 left join t1 on t2.program=t1.product and t2.value=t1.component where program="AAAAA" group by value having COUNT(bug_id) IN (0,2);
|
||||
value description COUNT(bug_id)
|
||||
BBBBBBBBBBBBB - conversion 2
|
||||
BBBBBBBBBBBBB - eeeeeeeee 0
|
||||
BBBBBBBBBBBBB - generic 2
|
||||
Documentation 0
|
||||
Host communication 0
|
||||
Test Procedures 0
|
||||
drop table t1,t2;
|
||||
create table t1 (foo int);
|
||||
insert into t1 values (1);
|
||||
|
|
@ -234,6 +242,13 @@ userid count(*)
|
|||
3 3
|
||||
2 1
|
||||
1 2
|
||||
select userid,count(*) from t1 group by userid desc having (count(*)+1) IN (4,3);
|
||||
userid count(*)
|
||||
3 3
|
||||
1 2
|
||||
select userid,count(*) from t1 group by userid desc having 3 IN (1,COUNT(*));
|
||||
userid count(*)
|
||||
3 3
|
||||
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range spID spID 5 NULL 2 Using where; Using index
|
||||
|
|
|
|||
|
|
@ -1021,3 +1021,40 @@ id code name
|
|||
7 4 Matt
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
drop table if exists t1,t2;
|
||||
create table t1 (n int(10), d int(10)) type=innodb;
|
||||
create table t2 (n int(10), d int(10)) type=innodb;
|
||||
insert into t1 values(1,1),(1,2);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
n d
|
||||
1 10
|
||||
1 10
|
||||
select * from t2;
|
||||
n d
|
||||
1 30
|
||||
2 20
|
||||
drop table t1,t2;
|
||||
create table t1 (a int, b int) type=innodb;
|
||||
insert into t1 values(20,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a;
|
||||
b ifnull(t2.b,"this is null")
|
||||
NULL this is null
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
b ifnull(t2.b,"this is null")
|
||||
NULL this is null
|
||||
insert into t1 values(10,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
b ifnull(t2.b,"this is null")
|
||||
NULL this is null
|
||||
NULL this is null
|
||||
drop table t1;
|
||||
create table t1 (a varchar(10) not null) type=myisam;
|
||||
create table t2 (b varchar(10) not null unique) type=innodb;
|
||||
select t1.a from t1,t2 where t1.a=t2.b;
|
||||
a
|
||||
drop table t1,t2;
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ count(*)
|
|||
10
|
||||
select count(*) from t2 where t = "bbb";
|
||||
count(*)
|
||||
10
|
||||
50
|
||||
select count(*) from t2 where id2 > 90;
|
||||
count(*)
|
||||
50
|
||||
|
|
@ -70,71 +70,61 @@ create table t1(id1 int not null primary key, t varchar(100)) pack_keys = 1;
|
|||
create table t2(id2 int not null, t varchar(100), index(id2)) pack_keys = 1;
|
||||
delete t1 from t1,t2 where t1.id1 = t2.id2 and t1.id1 > 500;
|
||||
drop table t1,t2;
|
||||
DROP TABLE IF EXISTS a,b,c;
|
||||
CREATE TABLE a (
|
||||
CREATE TABLE t1 (
|
||||
id int(11) NOT NULL default '0',
|
||||
name varchar(10) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO a VALUES (1,'aaa'),(2,'aaa'),(3,'aaa');
|
||||
CREATE TABLE b (
|
||||
INSERT INTO t1 VALUES (1,'aaa'),(2,'aaa'),(3,'aaa');
|
||||
CREATE TABLE t2 (
|
||||
id int(11) NOT NULL default '0',
|
||||
name varchar(10) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO b VALUES (2,'bbb'),(3,'bbb'),(4,'bbb');
|
||||
CREATE TABLE c (
|
||||
INSERT INTO t2 VALUES (2,'bbb'),(3,'bbb'),(4,'bbb');
|
||||
CREATE TABLE t3 (
|
||||
id int(11) NOT NULL default '0',
|
||||
mydate datetime default NULL,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO c VALUES (1,'2002-02-04 00:00:00'),(3,'2002-05-12 00:00:00'),(5,'2002-05-12 00:00:00'),(6,'2002-06-22
|
||||
INSERT INTO t3 VALUES (1,'2002-02-04 00:00:00'),(3,'2002-05-12 00:00:00'),(5,'2002-05-12 00:00:00'),(6,'2002-06-22
|
||||
00:00:00'),(7,'2002-07-22 00:00:00');
|
||||
delete a,b,c from a,b,c
|
||||
where to_days(now())-to_days(c.mydate)>=30
|
||||
and c.id=a.id and c.id=b.id;
|
||||
select * from c;
|
||||
delete t1,t2,t3 from t1,t2,t3 where to_days(now())-to_days(t3.mydate)>=30 and t3.id=t1.id and t3.id=t2.id;
|
||||
select * from t3;
|
||||
id mydate
|
||||
1 2002-02-04 00:00:00
|
||||
5 2002-05-12 00:00:00
|
||||
6 2002-06-22 00:00:00
|
||||
7 2002-07-22 00:00:00
|
||||
DROP TABLE IF EXISTS a,b,c;
|
||||
drop table if exists parent, child;
|
||||
CREATE TABLE IF NOT EXISTS `parent` (
|
||||
DROP TABLE IF EXISTS t1,t2,t3;
|
||||
CREATE TABLE IF NOT EXISTS `t1` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`tst` text,
|
||||
`tst1` text,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=MyISAM;
|
||||
CREATE TABLE IF NOT EXISTS `child` (
|
||||
CREATE TABLE IF NOT EXISTS `t2` (
|
||||
`ID` int(11) NOT NULL auto_increment,
|
||||
`ParId` int(11) default NULL,
|
||||
`tst` text,
|
||||
`tst1` text,
|
||||
PRIMARY KEY (`ID`),
|
||||
KEY `IX_ParId_child` (`ParId`),
|
||||
FOREIGN KEY (`ParId`) REFERENCES `test.parent` (`id`)
|
||||
KEY `IX_ParId_t2` (`ParId`),
|
||||
FOREIGN KEY (`ParId`) REFERENCES `t1` (`id`)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO parent(tst,tst1)
|
||||
VALUES("MySQL","MySQL AB"), ("MSSQL","Microsoft"), ("ORACLE","ORACLE");
|
||||
INSERT INTO child(ParId)
|
||||
VALUES(1), (2), (3);
|
||||
select * from child;
|
||||
INSERT INTO t1(tst,tst1) VALUES("MySQL","MySQL AB"), ("MSSQL","Microsoft"), ("ORACLE","ORACLE");
|
||||
INSERT INTO t2(ParId) VALUES(1), (2), (3);
|
||||
select * from t2;
|
||||
ID ParId tst tst1
|
||||
1 1 NULL NULL
|
||||
2 2 NULL NULL
|
||||
3 3 NULL NULL
|
||||
UPDATE child, parent
|
||||
SET child.tst = parent.tst,
|
||||
child.tst1 = parent.tst1
|
||||
WHERE child.ParId = parent.Id;
|
||||
select * from child;
|
||||
UPDATE t2, t1 SET t2.tst = t1.tst, t2.tst1 = t1.tst1 WHERE t2.ParId = t1.Id;
|
||||
select * from t2;
|
||||
ID ParId tst tst1
|
||||
1 1 MySQL MySQL AB
|
||||
2 2 MSSQL Microsoft
|
||||
3 3 ORACLE ORACLE
|
||||
drop table parent, child;
|
||||
drop table if exists t1, t2 ;
|
||||
create table t1 (n numeric(10));
|
||||
create table t2 (n numeric(10));
|
||||
|
|
@ -176,3 +166,73 @@ n d
|
|||
2 20
|
||||
unlock tables;
|
||||
drop table t1,t2;
|
||||
set sql_safe_updates=1;
|
||||
create table t1 (n int(10), d int(10));
|
||||
create table t2 (n int(10), d int(10));
|
||||
insert into t1 values(1,1);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
|
||||
You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column
|
||||
set sql_safe_updates=0;
|
||||
drop table t1,t2;
|
||||
set timestamp=1038401397;
|
||||
create table t1 (n int(10) not null primary key, d int(10), t timestamp);
|
||||
create table t2 (n int(10) not null primary key, d int(10), t timestamp);
|
||||
insert into t1 values(1,1,NULL);
|
||||
insert into t2 values(1,10,NULL),(2,20,NULL);
|
||||
set timestamp=1038000000;
|
||||
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
n d t
|
||||
1 10 20021123002000
|
||||
select * from t2;
|
||||
n d t
|
||||
1 10 20021127154957
|
||||
2 20 20021127154957
|
||||
UPDATE t1,t2 SET 1=2 WHERE t1.n=t2.n;
|
||||
You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use near '1=2 WHERE t1.n=t2.n' at line 1
|
||||
drop table t1,t2;
|
||||
set timestamp=0;
|
||||
set sql_safe_updates=0;
|
||||
create table t1 (n int(10) not null primary key, d int(10));
|
||||
create table t2 (n int(10) not null primary key, d int(10));
|
||||
insert into t1 values(1,1), (3,3);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t2 left outer join t1 on t1.n=t2.n SET t1.d=t2.d;
|
||||
select * from t1;
|
||||
n d
|
||||
1 10
|
||||
3 3
|
||||
select * from t2;
|
||||
n d
|
||||
1 10
|
||||
2 20
|
||||
drop table t1,t2;
|
||||
create table t1 (n int(10), d int(10));
|
||||
create table t2 (n int(10), d int(10));
|
||||
insert into t1 values(1,1),(1,2);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
n d
|
||||
1 10
|
||||
1 10
|
||||
select * from t2;
|
||||
n d
|
||||
1 30
|
||||
2 20
|
||||
drop table t1,t2;
|
||||
create table t1 (n int(10), d int(10));
|
||||
create table t2 (n int(10), d int(10));
|
||||
insert into t1 values(1,1),(3,2);
|
||||
insert into t2 values(1,10),(1,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
n d
|
||||
1 10
|
||||
3 2
|
||||
select * from t2;
|
||||
n d
|
||||
1 30
|
||||
1 30
|
||||
drop table t1,t2;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ select 1 | NULL,1 & NULL,1+NULL,1-NULL;
|
|||
NULL NULL NULL NULL
|
||||
select NULL=NULL,NULL<>NULL,IFNULL(NULL,1.1)+0,IFNULL(NULL,1) | 0;
|
||||
NULL=NULL NULL<>NULL IFNULL(NULL,1.1)+0 IFNULL(NULL,1) | 0
|
||||
NULL NULL 1.1 1
|
||||
NULL NULL 1 1
|
||||
select strcmp("a",NULL),(1<NULL)+0.0,NULL regexp "a",null like "a%","a%" like null;
|
||||
strcmp("a",NULL) (1<NULL)+0.0 NULL regexp "a" null like "a%" "a%" like null
|
||||
NULL NULL NULL NULL NULL
|
||||
|
|
@ -56,3 +56,20 @@ indexed_field
|
|||
NULL
|
||||
NULL
|
||||
DROP TABLE t1;
|
||||
create table t1 (a int, b int) type=myisam;
|
||||
insert into t1 values(20,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a;
|
||||
b ifnull(t2.b,"this is null")
|
||||
NULL this is null
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
b ifnull(t2.b,"this is null")
|
||||
NULL this is null
|
||||
insert into t1 values(10,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
b ifnull(t2.b,"this is null")
|
||||
NULL this is null
|
||||
NULL this is null
|
||||
drop table t1;
|
||||
|
|
|
|||
|
|
@ -3478,3 +3478,16 @@ a a a
|
|||
2 2 2
|
||||
3 3 3
|
||||
drop table t1;
|
||||
drop table if exists t1,t2;
|
||||
CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) TYPE=MyISAM;
|
||||
INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
|
||||
CREATE TABLE t2 ( id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;
|
||||
INSERT INTO t2 VALUES (2517), (2518), (2519), (2520), (2521), (2522);
|
||||
select * from t1, t2 WHERE t1.t2_id = t2.id and t1.t2_id > 0 order by t1.id LIMIT 0, 5;
|
||||
aa id t2_id id
|
||||
2 8299 2517 2517
|
||||
3 8301 2518 2518
|
||||
4 8302 2519 2519
|
||||
5 8303 2520 2520
|
||||
6 8304 2521 2521
|
||||
drop table if exists t1,t2;
|
||||
|
|
|
|||
|
|
@ -72,6 +72,11 @@ id val elt(two.val,'one','two')
|
|||
2 1 one
|
||||
4 2 two
|
||||
drop table t1,t2;
|
||||
create temporary table t1 (a int not null);
|
||||
insert into t1 values (1),(1);
|
||||
alter table t1 add primary key (a);
|
||||
Duplicate entry '1' for key 1
|
||||
drop table t1;
|
||||
drop table if exists t1;
|
||||
CREATE TABLE t1 (
|
||||
d datetime default NULL
|
||||
|
|
|
|||
|
|
@ -1,11 +1,31 @@
|
|||
drop table if exists t1;
|
||||
CREATE TABLE t1 ( t timestamp);
|
||||
drop table if exists t1,t2;
|
||||
CREATE TABLE t1 (a int, t timestamp);
|
||||
CREATE TABLE t2 (a int, t datetime);
|
||||
SET TIMESTAMP=1234;
|
||||
insert into t1 values(NULL);
|
||||
insert into t1 values(1,NULL);
|
||||
insert into t1 values(2,"2002-03-03");
|
||||
SET TIMESTAMP=1235;
|
||||
insert into t1 values(3,NULL);
|
||||
SET TIMESTAMP=1236;
|
||||
insert into t1 (a) values(4);
|
||||
insert into t2 values(5,"2002-03-04"),(6,NULL),(7,"2002-03-05"),(8,"00-00-00");
|
||||
SET TIMESTAMP=1237;
|
||||
insert into t1 select * from t2;
|
||||
SET TIMESTAMP=1238;
|
||||
insert into t1 (a) select a+1 from t2 where a=8;
|
||||
select * from t1;
|
||||
t
|
||||
19700101032034
|
||||
drop table t1;
|
||||
a t
|
||||
1 19700101032034
|
||||
2 20020303000000
|
||||
3 19700101032035
|
||||
4 19700101032036
|
||||
5 20020304000000
|
||||
6 19700101032037
|
||||
7 20020305000000
|
||||
8 00000000000000
|
||||
9 19700101032038
|
||||
drop table t1,t2;
|
||||
SET TIMESTAMP=1234;
|
||||
CREATE TABLE t1 (value TEXT NOT NULL, id VARCHAR(32) NOT NULL, stamp timestamp, PRIMARY KEY (id));
|
||||
INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
|
||||
SELECT stamp FROM t1 WHERE id="myKey";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# Test of alter table
|
||||
#
|
||||
|
||||
drop table if exists t1;
|
||||
drop table if exists t1,t2;
|
||||
create table t1 (
|
||||
col1 int not null auto_increment primary key,
|
||||
col2 varchar(30) not null,
|
||||
|
|
|
|||
|
|
@ -88,6 +88,16 @@ select distinct t1.a from t1,t3 where t1.a=t3.a;
|
|||
#flush status;
|
||||
select distinct 1 from t1,t3 where t1.a=t3.a;
|
||||
#show status like 'Handler%';
|
||||
|
||||
explain SELECT distinct t1.a from t1;
|
||||
explain SELECT distinct t1.a from t1 order by a desc;
|
||||
explain SELECT t1.a from t1 group by a order by a desc;
|
||||
explain SELECT distinct t1.a from t1 order by a desc limit 1;
|
||||
explain SELECT distinct a from t3 order by a desc limit 2;
|
||||
explain SELECT distinct a,b from t3 order by a+1;
|
||||
explain SELECT distinct a,b from t3 order by a limit 10;
|
||||
explain SELECT a,b from t3 group by a,b order by a+1;
|
||||
|
||||
drop table t1,t2,t3,t4;
|
||||
|
||||
CREATE TABLE t1 (name varchar(255));
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ select ln(exp(10)),exp(ln(sqrt(10))*2),ln(-1),ln(0),ln(NULL);
|
|||
select log2(8),log2(15),log2(-2),log2(0),log2(NULL);
|
||||
select log10(100),log10(18),log10(-4),log10(0),log10(NULL);
|
||||
select pow(10,log10(10)),power(2,4);
|
||||
set @@rand_seed1=10000000,@@rand_seed2=1000000;
|
||||
select rand(999999),rand();
|
||||
select pi(),sin(pi()/2),cos(pi()/2),abs(tan(pi())),cot(1),asin(1),acos(0),atan(1);
|
||||
select degrees(pi()),radians(360);
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ INSERT INTO t2 VALUES ('Web Interface','AAAAAAAA-AAA','id0001','','');
|
|||
INSERT INTO t2 VALUES ('Host communication','AAAAA','id0001','','');
|
||||
select value,description,bug_id from t2 left join t1 on t2.program=t1.product and t2.value=t1.component where program="AAAAA";
|
||||
select value,description,COUNT(bug_id) from t2 left join t1 on t2.program=t1.product and t2.value=t1.component where program="AAAAA" group by value;
|
||||
select value,description,COUNT(bug_id) from t2 left join t1 on t2.program=t1.product and t2.value=t1.component where program="AAAAA" group by value having COUNT(bug_id) IN (0,2);
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
|
|
@ -236,6 +237,8 @@ CREATE TABLE t1 (
|
|||
INSERT INTO t1 VALUES (1,1,1),(2,2,2),(2,1,1),(3,3,3),(4,3,3),(5,3,3);
|
||||
explain select userid,count(*) from t1 group by userid desc;
|
||||
select userid,count(*) from t1 group by userid desc;
|
||||
select userid,count(*) from t1 group by userid desc having (count(*)+1) IN (4,3);
|
||||
select userid,count(*) from t1 group by userid desc having 3 IN (1,COUNT(*));
|
||||
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid desc;
|
||||
explain select spid,count(*) from t1 where spid between 1 and 2 group by spid;
|
||||
select spid,count(*) from t1 where spid between 1 and 2 group by spid;
|
||||
|
|
|
|||
|
|
@ -660,3 +660,39 @@ insert into t1 (code, name) values (3, 'Jeremy'), (4, 'Matt');
|
|||
select id, code, name from t1 order by id;
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Test of multi-table-update
|
||||
#
|
||||
drop table if exists t1,t2;
|
||||
create table t1 (n int(10), d int(10)) type=innodb;
|
||||
create table t2 (n int(10), d int(10)) type=innodb;
|
||||
insert into t1 values(1,1),(1,2);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Testing of IFNULL
|
||||
#
|
||||
create table t1 (a int, b int) type=innodb;
|
||||
insert into t1 values(20,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a;
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
insert into t1 values(10,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test of read_through not existing const_table
|
||||
#
|
||||
|
||||
create table t1 (a varchar(10) not null) type=myisam;
|
||||
create table t2 (b varchar(10) not null unique) type=innodb;
|
||||
select t1.a from t1,t2 where t1.a=t2.b;
|
||||
drop table t1,t2;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
#
|
||||
# Only run the test if we are using --big-test, because this test takes a
|
||||
# long time
|
||||
# Test of update statement that uses many tables.
|
||||
#
|
||||
#-- require r/big_test.require
|
||||
#eval select $BIG_TEST as using_big_test;
|
||||
|
||||
drop table if exists t1,t2,t3;
|
||||
create table t1(id1 int not null auto_increment primary key, t char(12));
|
||||
|
|
@ -80,67 +77,59 @@ while ($1)
|
|||
enable_query_log;
|
||||
delete t1 from t1,t2 where t1.id1 = t2.id2 and t1.id1 > 500;
|
||||
drop table t1,t2;
|
||||
DROP TABLE IF EXISTS a,b,c;
|
||||
CREATE TABLE a (
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id int(11) NOT NULL default '0',
|
||||
name varchar(10) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO a VALUES (1,'aaa'),(2,'aaa'),(3,'aaa');
|
||||
CREATE TABLE b (
|
||||
INSERT INTO t1 VALUES (1,'aaa'),(2,'aaa'),(3,'aaa');
|
||||
CREATE TABLE t2 (
|
||||
id int(11) NOT NULL default '0',
|
||||
name varchar(10) default NULL,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO b VALUES (2,'bbb'),(3,'bbb'),(4,'bbb');
|
||||
CREATE TABLE c (
|
||||
INSERT INTO t2 VALUES (2,'bbb'),(3,'bbb'),(4,'bbb');
|
||||
CREATE TABLE t3 (
|
||||
id int(11) NOT NULL default '0',
|
||||
mydate datetime default NULL,
|
||||
PRIMARY KEY (id)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO c VALUES (1,'2002-02-04 00:00:00'),(3,'2002-05-12 00:00:00'),(5,'2002-05-12 00:00:00'),(6,'2002-06-22
|
||||
INSERT INTO t3 VALUES (1,'2002-02-04 00:00:00'),(3,'2002-05-12 00:00:00'),(5,'2002-05-12 00:00:00'),(6,'2002-06-22
|
||||
00:00:00'),(7,'2002-07-22 00:00:00');
|
||||
delete a,b,c from a,b,c
|
||||
where to_days(now())-to_days(c.mydate)>=30
|
||||
and c.id=a.id and c.id=b.id;
|
||||
select * from c;
|
||||
DROP TABLE IF EXISTS a,b,c;
|
||||
drop table if exists parent, child;
|
||||
CREATE TABLE IF NOT EXISTS `parent` (
|
||||
delete t1,t2,t3 from t1,t2,t3 where to_days(now())-to_days(t3.mydate)>=30 and t3.id=t1.id and t3.id=t2.id;
|
||||
select * from t3;
|
||||
DROP TABLE IF EXISTS t1,t2,t3;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `t1` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`tst` text,
|
||||
`tst1` text,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `child` (
|
||||
CREATE TABLE IF NOT EXISTS `t2` (
|
||||
`ID` int(11) NOT NULL auto_increment,
|
||||
`ParId` int(11) default NULL,
|
||||
`tst` text,
|
||||
`tst1` text,
|
||||
PRIMARY KEY (`ID`),
|
||||
KEY `IX_ParId_child` (`ParId`),
|
||||
FOREIGN KEY (`ParId`) REFERENCES `test.parent` (`id`)
|
||||
KEY `IX_ParId_t2` (`ParId`),
|
||||
FOREIGN KEY (`ParId`) REFERENCES `t1` (`id`)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
INSERT INTO parent(tst,tst1)
|
||||
VALUES("MySQL","MySQL AB"), ("MSSQL","Microsoft"), ("ORACLE","ORACLE");
|
||||
INSERT INTO t1(tst,tst1) VALUES("MySQL","MySQL AB"), ("MSSQL","Microsoft"), ("ORACLE","ORACLE");
|
||||
|
||||
INSERT INTO child(ParId)
|
||||
VALUES(1), (2), (3);
|
||||
INSERT INTO t2(ParId) VALUES(1), (2), (3);
|
||||
|
||||
select * from child;
|
||||
select * from t2;
|
||||
|
||||
UPDATE child, parent
|
||||
SET child.tst = parent.tst,
|
||||
child.tst1 = parent.tst1
|
||||
WHERE child.ParId = parent.Id;
|
||||
UPDATE t2, t1 SET t2.tst = t1.tst, t2.tst1 = t1.tst1 WHERE t2.ParId = t1.Id;
|
||||
|
||||
select * from child;
|
||||
select * from t2;
|
||||
|
||||
|
||||
drop table parent, child;
|
||||
drop table if exists t1, t2 ;
|
||||
|
||||
create table t1 (n numeric(10));
|
||||
create table t2 (n numeric(10));
|
||||
insert into t2 values (1),(2),(4),(8),(16),(32);
|
||||
|
|
@ -174,3 +163,54 @@ select * from t1;
|
|||
select * from t2;
|
||||
unlock tables;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Test safe updates and timestamps
|
||||
#
|
||||
set sql_safe_updates=1;
|
||||
create table t1 (n int(10), d int(10));
|
||||
create table t2 (n int(10), d int(10));
|
||||
insert into t1 values(1,1);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
--error 1175
|
||||
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
|
||||
set sql_safe_updates=0;
|
||||
drop table t1,t2;
|
||||
set timestamp=1038401397;
|
||||
create table t1 (n int(10) not null primary key, d int(10), t timestamp);
|
||||
create table t2 (n int(10) not null primary key, d int(10), t timestamp);
|
||||
insert into t1 values(1,1,NULL);
|
||||
insert into t2 values(1,10,NULL),(2,20,NULL);
|
||||
set timestamp=1038000000;
|
||||
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
--error 1064
|
||||
UPDATE t1,t2 SET 1=2 WHERE t1.n=t2.n;
|
||||
drop table t1,t2;
|
||||
set timestamp=0;
|
||||
set sql_safe_updates=0;
|
||||
create table t1 (n int(10) not null primary key, d int(10));
|
||||
create table t2 (n int(10) not null primary key, d int(10));
|
||||
insert into t1 values(1,1), (3,3);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t2 left outer join t1 on t1.n=t2.n SET t1.d=t2.d;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
drop table t1,t2;
|
||||
create table t1 (n int(10), d int(10));
|
||||
create table t2 (n int(10), d int(10));
|
||||
insert into t1 values(1,1),(1,2);
|
||||
insert into t2 values(1,10),(2,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
drop table t1,t2;
|
||||
create table t1 (n int(10), d int(10));
|
||||
create table t2 (n int(10), d int(10));
|
||||
insert into t1 values(1,1),(3,2);
|
||||
insert into t2 values(1,10),(1,20);
|
||||
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
drop table t1,t2;
|
||||
|
|
|
|||
|
|
@ -34,3 +34,17 @@ SELECT * FROM t1 WHERE indexed_field=NULL;
|
|||
SELECT * FROM t1 WHERE indexed_field IS NULL;
|
||||
SELECT * FROM t1 WHERE indexed_field<=>NULL;
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Testing of IFNULL
|
||||
#
|
||||
create table t1 (a int, b int) type=myisam;
|
||||
insert into t1 values(20,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a;
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
insert into t1 values(10,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
t2.b=t3.a order by 1;
|
||||
drop table t1;
|
||||
|
|
|
|||
|
|
@ -1799,5 +1799,11 @@ select * from t1 natural right join (t1 as t2 left join t1 as t3 using (a));
|
|||
# natural join
|
||||
select * from t1 natural join (t1 as t2 left join t1 as t3 using (a));
|
||||
select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
|
||||
|
||||
drop table t1;
|
||||
drop table if exists t1,t2;
|
||||
CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) TYPE=MyISAM;
|
||||
INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
|
||||
CREATE TABLE t2 ( id int(11) NOT NULL auto_increment, PRIMARY KEY (id)) TYPE=MyISAM;
|
||||
INSERT INTO t2 VALUES (2517), (2518), (2519), (2520), (2521), (2522);
|
||||
select * from t1, t2 WHERE t1.t2_id = t2.id and t1.t2_id > 0 order by t1.id LIMIT 0, 5;
|
||||
drop table if exists t1,t2;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,15 @@ insert into t2 values (1,1),(2,1),(3,1),(4,2);
|
|||
select one.id, two.val, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Test of failed ALTER TABLE on temporary table
|
||||
#
|
||||
create temporary table t1 (a int not null);
|
||||
insert into t1 values (1),(1);
|
||||
-- error 1062
|
||||
alter table t1 add primary key (a);
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# In MySQL 4.0.4 doing a GROUP BY on a NULL column created a disk based
|
||||
# temporary table when a memory based one would be good enough.
|
||||
|
|
|
|||
|
|
@ -2,14 +2,25 @@
|
|||
# Test timestamp
|
||||
#
|
||||
|
||||
drop table if exists t1;
|
||||
CREATE TABLE t1 ( t timestamp);
|
||||
drop table if exists t1,t2;
|
||||
CREATE TABLE t1 (a int, t timestamp);
|
||||
CREATE TABLE t2 (a int, t datetime);
|
||||
SET TIMESTAMP=1234;
|
||||
insert into t1 values(NULL);
|
||||
insert into t1 values(1,NULL);
|
||||
insert into t1 values(2,"2002-03-03");
|
||||
SET TIMESTAMP=1235;
|
||||
insert into t1 values(3,NULL);
|
||||
SET TIMESTAMP=1236;
|
||||
insert into t1 (a) values(4);
|
||||
insert into t2 values(5,"2002-03-04"),(6,NULL),(7,"2002-03-05"),(8,"00-00-00");
|
||||
SET TIMESTAMP=1237;
|
||||
insert into t1 select * from t2;
|
||||
SET TIMESTAMP=1238;
|
||||
insert into t1 (a) select a+1 from t2 where a=8;
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
SET TIMESTAMP=1234;
|
||||
CREATE TABLE t1 (value TEXT NOT NULL, id VARCHAR(32) NOT NULL, stamp timestamp, PRIMARY KEY (id));
|
||||
INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
|
||||
SELECT stamp FROM t1 WHERE id="myKey";
|
||||
|
|
|
|||
|
|
@ -445,6 +445,8 @@ void init_io_cache_share(IO_CACHE *info, IO_CACHE_SHARE *s, uint num_threads)
|
|||
s->active=0; /* to catch errors */
|
||||
info->share=s;
|
||||
info->read_function=_my_b_read_r;
|
||||
/* Ensure that the code doesn't use pointer to the IO_CACHE object */
|
||||
info->current_pos= info->current_end= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -280,13 +280,14 @@ report("Order by function","order_by_function",
|
|||
"select a from crash_me order by a+1");
|
||||
report("Order by on unused column",'order_on_unused',
|
||||
"select b from crash_me order by a");
|
||||
check_and_report("Order by DESC is remembered",'order_by_remember_desc',
|
||||
["create table crash_q (s int,s1 int)",
|
||||
"insert into crash_q values(1,1)",
|
||||
"insert into crash_q values(3,1)",
|
||||
"insert into crash_q values(2,1)"],
|
||||
"select s,s1 from crash_q order by s1 DESC,s",
|
||||
["drop table crash_q $drop_attr"],[3,2,1],7,undef(),3);
|
||||
# little bit deprecated
|
||||
#check_and_report("Order by DESC is remembered",'order_by_remember_desc',
|
||||
# ["create table crash_q (s int,s1 int)",
|
||||
# "insert into crash_q values(1,1)",
|
||||
# "insert into crash_q values(3,1)",
|
||||
# "insert into crash_q values(2,1)"],
|
||||
# "select s,s1 from crash_q order by s1 DESC,s",
|
||||
# ["drop table crash_q $drop_attr"],[3,2,1],7,undef(),3);
|
||||
report("Compute",'compute',
|
||||
"select a from crash_me order by a compute sum(a) by a");
|
||||
report("INSERT with Value lists",'insert_multi_value',
|
||||
|
|
@ -844,7 +845,6 @@ try_and_report("Automatic row id", "automatic_rowid",
|
|||
["DAYOFWEEK","dayofweek","dayofweek(DATE '1997-02-01')",7,0],
|
||||
["DAYOFYEAR","dayofyear","dayofyear(DATE '1997-02-01')",32,0],
|
||||
["QUARTER","quarter","quarter(DATE '1997-02-01')",1,0],
|
||||
["WEEK","week","week(DATE '1997-02-01')",5,0],
|
||||
["YEAR","year","year(DATE '1997-02-01')",1997,0],
|
||||
["CURTIME","curtime","curtime()",0,2],
|
||||
["HOUR","hour","hour('12:13:14')",12,0],
|
||||
|
|
@ -980,7 +980,6 @@ try_and_report("Automatic row id", "automatic_rowid",
|
|||
["ASCII in string cast",'ascii_string',"ascii('a')",'a',1],
|
||||
["EBCDIC in string cast",'ebcdic_string',"ebcdic('a')",'a',1],
|
||||
["TRUNC (1 arg)",'trunc1arg',"trunc(222.6)",222,0],
|
||||
["NOROUND",'noround',"noround(222.6)",222.6,0],
|
||||
["FIXED",'fixed',"fixed(222.6666,10,2)",'222.67',0],
|
||||
["FLOAT",'float',"float(6666.66,4)",6667,0],
|
||||
["LENGTH",'length',"length(1)",2,0],
|
||||
|
|
@ -1187,12 +1186,31 @@ else
|
|||
}
|
||||
|
||||
|
||||
if ($limits{'func_extra_noround'} eq 'yes')
|
||||
# Test: NOROUND
|
||||
{
|
||||
report("Ignoring NOROUND","ignoring_noround",
|
||||
"create table crash_q (a int)",
|
||||
"insert into crash_q values(noround(10.22))",
|
||||
"drop table crash_q $drop_attr");
|
||||
my $resultat = 'undefined';
|
||||
my $error;
|
||||
print "NOROUND: ";
|
||||
save_incomplete('func_extra_noround','Function NOROUND');
|
||||
|
||||
# 1) check if noround() function is supported
|
||||
$error = safe_query("select noround(22.6) $end_query");
|
||||
if ($error ne 1) # syntax error -- noround is not supported
|
||||
{
|
||||
$resultat = 'no'
|
||||
} else # Ok, now check if it really works
|
||||
{
|
||||
$error=safe_query( "create table crash_me_nr (a int)",
|
||||
"insert into crash_me_nr values(noround(10.2))",
|
||||
"drop table crash_me_nr $drop_attr");
|
||||
if ($error eq 1) {
|
||||
$resultat = "syntax only";
|
||||
} else {
|
||||
$resultat = 'yes';
|
||||
}
|
||||
}
|
||||
print "$resultat\n";
|
||||
save_config_data('func_extra_noround',$resultat,"Function NOROUND");
|
||||
}
|
||||
|
||||
check_parenthesis("func_sql_","CURRENT_USER");
|
||||
|
|
@ -1200,6 +1218,32 @@ check_parenthesis("func_sql_","SESSION_USER");
|
|||
check_parenthesis("func_sql_","SYSTEM_USER");
|
||||
check_parenthesis("func_sql_","USER");
|
||||
|
||||
# Test: WEEK()
|
||||
{
|
||||
my $explain="";
|
||||
my $resultat="no";
|
||||
my $error;
|
||||
print "WEEK:";
|
||||
save_incomplete('func_odbc_week','WEEK');
|
||||
$error = safe_query_result("select week(DATE '1997-02-01') $end_query",5,0);
|
||||
# actually this query must return 4 or 5 in the $last_result,
|
||||
# $error can be 1 (not supported at all) , -1 ( probably USA weeks)
|
||||
# and 0 - EURO weeks
|
||||
if ($error == -1) {
|
||||
if ($last_result == 4) {
|
||||
$resultat = 'USA';
|
||||
$explain = ' started from Sunday';
|
||||
} else {
|
||||
$resultat='error';
|
||||
$explain = " must return 4 or 5, but $last_error";
|
||||
}
|
||||
} elsif ($error == 0) {
|
||||
$resultat = 'EURO';
|
||||
$explain = ' started from Monday';
|
||||
}
|
||||
print " $resultat\n";
|
||||
save_config_data('func_odbc_week',$resultat,"WEEK $explain");
|
||||
}
|
||||
|
||||
report("LIKE on numbers","like_with_number",
|
||||
"create table crash_q (a int,b int)",
|
||||
|
|
@ -1682,28 +1726,36 @@ report("views","views",
|
|||
"create view crash_q as select a from crash_me",
|
||||
"drop view crash_q $drop_attr");
|
||||
|
||||
report("foreign key syntax","foreign_key_syntax",
|
||||
create_table("crash_q",["a integer not null"],["primary key (a)"]),
|
||||
create_table("crash_q2",["a integer not null",
|
||||
"foreign key (a) references crash_q (a)"],
|
||||
[]),
|
||||
"insert into crash_q values (1)",
|
||||
"insert into crash_q2 values (1)",
|
||||
"drop table crash_q2 $drop_attr",
|
||||
"drop table crash_q $drop_attr");
|
||||
|
||||
if ($limits{'foreign_key_syntax'} eq 'yes')
|
||||
# Test: foreign key
|
||||
{
|
||||
report_fail("foreign keys","foreign_key",
|
||||
create_table("crash_q",["a integer not null"],
|
||||
["primary key (a)"]),
|
||||
create_table("crash_q2",["a integer not null",
|
||||
"foreign key (a) references crash_q (a)"],
|
||||
[]),
|
||||
"insert into crash_q values (1)",
|
||||
"insert into crash_q2 values (2)",
|
||||
"drop table crash_q2 $drop_attr",
|
||||
"drop table crash_q $drop_attr");
|
||||
my $resultat = 'undefined';
|
||||
my $error;
|
||||
print "foreign keys: ";
|
||||
save_incomplete('foreign_key','foreign keys');
|
||||
|
||||
# 1) check if foreign keys are supported
|
||||
safe_query(create_table("crash_me_qf",["a integer not null"],
|
||||
["primary key (a)"]));
|
||||
$error = safe_query( create_table("crash_me_qf2",["a integer not null",
|
||||
"foreign key (a) references crash_me_qf (a)"], []));
|
||||
|
||||
if ($error eq 1) # OK -- syntax is supported
|
||||
{
|
||||
$resultat = 'error';
|
||||
# now check if foreign key really works
|
||||
safe_query( "insert into crash_me_qf values (1)");
|
||||
if (safe_query( "insert into crash_me_qf2 values (2)") eq 1) {
|
||||
$resultat = 'syntax only';
|
||||
} else {
|
||||
$resultat = 'yes';
|
||||
}
|
||||
|
||||
} else {
|
||||
$resultat = "no";
|
||||
}
|
||||
safe_query( "drop table crash_me_qf2 $drop_attr","drop table crash_me_qf $drop_attr");
|
||||
print "$resultat\n";
|
||||
save_config_data('foreign_key',$resultat,"foreign keys");
|
||||
}
|
||||
|
||||
report("Create SCHEMA","create_schema",
|
||||
|
|
@ -1720,32 +1772,22 @@ if ($limits{'foreign_key'} eq 'yes')
|
|||
}
|
||||
}
|
||||
|
||||
report("Column constraints","constraint_check",
|
||||
"create table crash_q (a int check (a>0))",
|
||||
"drop table crash_q $drop_attr");
|
||||
|
||||
report("Ignoring column constraints","ignoring_constraint_check",
|
||||
check_constraint("Column constraints","constraint_check",
|
||||
"create table crash_q (a int check (a>0))",
|
||||
"insert into crash_q values(0)",
|
||||
"drop table crash_q $drop_attr") if ($limits{'constraint_check'} eq 'yes');
|
||||
|
||||
report("Table constraints","constraint_check_table",
|
||||
"create table crash_q (a int ,b int, check (a>b))",
|
||||
"drop table crash_q $drop_attr");
|
||||
|
||||
report("Ignoring table constraints","ignoring_constraint_check_table",
|
||||
|
||||
check_constraint("Table constraints","constraint_check_table",
|
||||
"create table crash_q (a int ,b int, check (a>b))",
|
||||
"insert into crash_q values(0,0)",
|
||||
"drop table crash_q $drop_attr") if ($limits{'constraint_check_table'} eq 'yes');
|
||||
|
||||
report("Named constraints","constraint_check_named",
|
||||
"create table crash_q (a int ,b int, constraint abc check (a>b))",
|
||||
"drop table crash_q $drop_attr");
|
||||
|
||||
report("Ignoring named constraints","ignoring_constraint_check_named",
|
||||
check_constraint("Named constraints","constraint_check_named",
|
||||
"create table crash_q (a int ,b int, constraint abc check (a>b))",
|
||||
"insert into crash_q values(0,0)",
|
||||
"drop table crash_q $drop_attr") if ($limits{'constraint_check_named'} eq 'yes');
|
||||
"drop table crash_q $drop_attr");
|
||||
|
||||
|
||||
report("NULL constraint (SyBase style)","constraint_null",
|
||||
"create table crash_q (a int null)",
|
||||
|
|
@ -2236,6 +2278,29 @@ sub check_parenthesis {
|
|||
save_config_data($param_name,$resultat,$fn);
|
||||
}
|
||||
|
||||
sub check_constraint {
|
||||
my $prompt = shift;
|
||||
my $key = shift;
|
||||
my $create = shift;
|
||||
my $check = shift;
|
||||
my $drop = shift;
|
||||
save_incomplete($key,$prompt);
|
||||
print "$prompt=";
|
||||
my $res = 'no';
|
||||
|
||||
if ( ($t=safe_query($create)) == 1)
|
||||
{
|
||||
$res='yes';
|
||||
if (safe_query($check) == 1)
|
||||
{
|
||||
$res='syntax only';
|
||||
}
|
||||
}
|
||||
safe_query($drop);
|
||||
save_config_data($key,$res,$prompt);
|
||||
print "$res\n";
|
||||
}
|
||||
|
||||
sub usage
|
||||
{
|
||||
print <<EOF;
|
||||
|
|
@ -2317,7 +2382,7 @@ $0 takes the following options:
|
|||
--user='user_name'
|
||||
User name to log into the SQL server.
|
||||
|
||||
--start-cmd='command to restart server'
|
||||
--db-start-cmd='command to restart server'
|
||||
Automaticly restarts server with this command if the database server dies.
|
||||
|
||||
--sleep='time in seconds' (Default $opt_sleep)
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ sub version
|
|||
}
|
||||
$sth->finish;
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +252,7 @@ sub create
|
|||
$query="create table $table_name (";
|
||||
foreach $field (@$fields)
|
||||
{
|
||||
$field =~ s/ decimal/ double(10,2)/i;
|
||||
# $field =~ s/ decimal/ double(10,2)/i;
|
||||
$field =~ s/ big_decimal/ double(10,2)/i;
|
||||
$query.= $field . ',';
|
||||
}
|
||||
|
|
@ -431,6 +432,8 @@ sub version
|
|||
{ # Strip pre- and endspace
|
||||
$tmp=$1;
|
||||
$tmp =~ s/\s+/ /g; # Remove unnecessary spaces
|
||||
$tmp .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
|
||||
return $tmp;
|
||||
}
|
||||
}
|
||||
|
|
@ -619,6 +622,7 @@ sub new
|
|||
sub version
|
||||
{
|
||||
my ($version,$dir);
|
||||
$version = "PostgreSQL version ???";
|
||||
foreach $dir ($ENV{'PGDATA'},"/usr/local/pgsql/data", "/usr/local/pg/data")
|
||||
{
|
||||
if ($dir && -e "$dir/PG_VERSION")
|
||||
|
|
@ -627,11 +631,13 @@ sub version
|
|||
if ($? == 0)
|
||||
{
|
||||
chomp($version);
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return "PostgreSQL $version";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "PostgreSQL version ???";
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -895,6 +901,7 @@ sub new
|
|||
sub version
|
||||
{
|
||||
my ($version,$dir);
|
||||
$version="Solid version ??";
|
||||
foreach $dir ($ENV{'SOLIDDIR'},"/usr/local/solid", "/my/local/solid")
|
||||
{
|
||||
if ($dir && -e "$dir/bin/solcon")
|
||||
|
|
@ -903,11 +910,13 @@ sub version
|
|||
if ($? == 0)
|
||||
{
|
||||
chomp($version);
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "Solid version ???";
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
sub connect
|
||||
|
|
@ -1136,6 +1145,8 @@ sub version
|
|||
{
|
||||
$version="Empress version ???";
|
||||
}
|
||||
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -1403,6 +1414,7 @@ sub version
|
|||
}
|
||||
$sth->finish;
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -1647,6 +1659,7 @@ sub version
|
|||
}
|
||||
$sth->finish;
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -1846,7 +1859,9 @@ sub new
|
|||
sub version
|
||||
{
|
||||
my ($self)=@_;
|
||||
return "Access 2000"; #DBI/ODBC can't return the server version
|
||||
my $version="Access 2000";
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version; #DBI/ODBC can't return the server version
|
||||
}
|
||||
|
||||
sub connect
|
||||
|
|
@ -2028,7 +2043,8 @@ sub new
|
|||
sub version
|
||||
{
|
||||
my ($self)=@_;
|
||||
my($sth,@row);
|
||||
my($sth,@row, $version);
|
||||
$version='MS SQL server ?';
|
||||
$dbh=$self->connect();
|
||||
$sth = $dbh->prepare("SELECT \@\@VERSION") or die $DBI::errstr;
|
||||
$sth->execute or die $DBI::errstr;
|
||||
|
|
@ -2036,10 +2052,11 @@ sub version
|
|||
if ($row[0]) {
|
||||
@server = split(/\n/,$row[0]);
|
||||
chomp(@server);
|
||||
return "$server[0]";
|
||||
} else {
|
||||
return "Microsoft SQL server ?";
|
||||
$version= "$server[0]";
|
||||
}
|
||||
$sth->finish;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
sub connect
|
||||
|
|
@ -2232,8 +2249,8 @@ sub version
|
|||
}
|
||||
$sth->finish;
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
|
||||
}
|
||||
|
||||
sub connect
|
||||
|
|
@ -2466,6 +2483,7 @@ sub version
|
|||
}
|
||||
$sth->finish;
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -2842,6 +2860,7 @@ sub version
|
|||
#
|
||||
$version = $dbh->func(18, GetInfo);
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -3041,6 +3060,7 @@ sub version
|
|||
# $version =~ s/.*version \"(.*)\"$/$1/;
|
||||
$dbh->disconnect;
|
||||
$version = "6.0Beta";
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -3246,6 +3266,7 @@ sub version
|
|||
#$version = $dbh->func(18, GetInfo);
|
||||
$version="FrontBase 3.3";
|
||||
# $dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
@ -3365,7 +3386,7 @@ sub fix_for_insert
|
|||
# Configuration for SAPDB
|
||||
#############################################################################
|
||||
|
||||
package db_Sapdb;
|
||||
package db_sapdb;
|
||||
|
||||
sub new
|
||||
{
|
||||
|
|
@ -3453,6 +3474,7 @@ sub version
|
|||
}
|
||||
$sth->finish;
|
||||
$dbh->disconnect;
|
||||
$version .= "/ODBC" if ($self->{'data_source'} =~ /:ODBC:/);
|
||||
return $version;
|
||||
}
|
||||
|
||||
|
|
|
|||
26
sql/field.cc
26
sql/field.cc
|
|
@ -1576,11 +1576,14 @@ void Field_medium::sql_type(String &res) const
|
|||
|
||||
int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
|
||||
{
|
||||
char *end;
|
||||
while (len && my_isspace(system_charset_info,*from))
|
||||
{
|
||||
len--; from++;
|
||||
}
|
||||
long tmp;
|
||||
String tmp_str(from,len);
|
||||
from= tmp_str.c_ptr(); // Add end null if needed
|
||||
int error= 0;
|
||||
errno=0;
|
||||
if (unsigned_flag)
|
||||
|
|
@ -1592,12 +1595,13 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
|
|||
error= 1;
|
||||
}
|
||||
else
|
||||
tmp=(long) my_strntoul(cs,from,len,NULL,10);
|
||||
tmp=(long) my_strntoul(cs,from,len,&end,10);
|
||||
}
|
||||
else
|
||||
tmp=my_strntol(cs,from,len,NULL,10);
|
||||
if (errno || current_thd->count_cuted_fields && !test_if_int(from,len))
|
||||
{
|
||||
tmp=my_strntol(cs,from,len,&end,10);
|
||||
if (errno ||
|
||||
(from+len != end && current_thd->count_cuted_fields &&
|
||||
!test_if_int(from,len)))
|
||||
current_thd->cuted_fields++;
|
||||
error= 1;
|
||||
}
|
||||
|
|
@ -1821,11 +1825,14 @@ void Field_long::sql_type(String &res) const
|
|||
|
||||
int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
|
||||
{
|
||||
char *end;
|
||||
while (len && my_isspace(system_charset_info,*from))
|
||||
{ // For easy error check
|
||||
len--; from++;
|
||||
}
|
||||
longlong tmp;
|
||||
String tmp_str(from,len);
|
||||
from= tmp_str.c_ptr(); // Add end null if needed
|
||||
int error= 0;
|
||||
errno=0;
|
||||
if (unsigned_flag)
|
||||
|
|
@ -1837,15 +1844,14 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
|
|||
error= 1;
|
||||
}
|
||||
else
|
||||
tmp=(longlong) my_strntoull(cs,from,len,NULL,10);
|
||||
tmp=(longlong) my_strntoull(cs,from,len,&end,10);
|
||||
}
|
||||
else
|
||||
tmp=my_strntoll(cs,from,len,NULL,10);
|
||||
if (errno || current_thd->count_cuted_fields && !test_if_int(from,len))
|
||||
{
|
||||
tmp=my_strntoll(cs,from,len,&end,10);
|
||||
if (errno ||
|
||||
(from+len != end && current_thd->count_cuted_fields &&
|
||||
!test_if_int(from,len)))
|
||||
current_thd->cuted_fields++;
|
||||
error= 1;
|
||||
}
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
if (table->db_low_byte_first)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,7 @@ Field *make_field(char *ptr, uint32 field_length,
|
|||
uint pack_length_to_packflag(uint type);
|
||||
uint32 calc_pack_length(enum_field_types type,uint32 length);
|
||||
bool set_field_to_null(Field *field);
|
||||
bool set_field_to_null_with_conversions(Field *field);
|
||||
bool set_field_to_null_with_conversions(Field *field, bool no_conversions);
|
||||
uint find_enum(TYPELIB *typelib,const char *x, uint length);
|
||||
ulonglong find_set(TYPELIB *typelib,const char *x, uint length);
|
||||
bool test_if_int(const char *str,int length);
|
||||
|
|
|
|||
|
|
@ -122,8 +122,26 @@ set_field_to_null(Field *field)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Set field to NULL or TIMESTAMP or to next auto_increment number
|
||||
|
||||
SYNOPSIS
|
||||
set_field_to_null_with_conversions()
|
||||
field Field to update
|
||||
no_conversion Set to 1 if we should return 1 if field can't
|
||||
take null values.
|
||||
If set to 0 we will do store the 'default value'
|
||||
if the field is a special field. If not we will
|
||||
give an error.
|
||||
|
||||
RETURN VALUES
|
||||
0 Field could take 0 or an automatic conversion was used
|
||||
1 Field could not take NULL and no conversion was used.
|
||||
If no_conversion was not set, an error message is printed
|
||||
*/
|
||||
|
||||
bool
|
||||
set_field_to_null_with_conversions(Field *field)
|
||||
set_field_to_null_with_conversions(Field *field, bool no_conversions)
|
||||
{
|
||||
if (field->real_maybe_null())
|
||||
{
|
||||
|
|
@ -131,6 +149,8 @@ set_field_to_null_with_conversions(Field *field)
|
|||
field->reset();
|
||||
return 0;
|
||||
}
|
||||
if (no_conversions)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
Check if this is a special type, which will get a special walue
|
||||
|
|
@ -156,8 +176,6 @@ set_field_to_null_with_conversions(Field *field)
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void do_skip(Copy_field *copy __attribute__((unused)))
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,10 +90,11 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
|||
are determined in innobase_init below: */
|
||||
|
||||
char* innobase_data_home_dir = NULL;
|
||||
char* innobase_data_file_path = NULL;
|
||||
char* innobase_log_group_home_dir = NULL;
|
||||
char* innobase_log_arch_dir = NULL;
|
||||
/* The following has a midleading name: starting from 4.0.5 this also
|
||||
affects Windows */
|
||||
/* The following has a misleading name: starting from 4.0.5, this also
|
||||
affects Windows: */
|
||||
char* innobase_unix_file_flush_method = NULL;
|
||||
|
||||
/* Below we have boolean-valued start-up parameters, and their default
|
||||
|
|
@ -104,14 +105,7 @@ my_bool innobase_log_archive = FALSE;
|
|||
my_bool innobase_use_native_aio = FALSE;
|
||||
my_bool innobase_fast_shutdown = TRUE;
|
||||
|
||||
/*
|
||||
Set default InnoDB data file size to 10 MB and let it be
|
||||
auto-extending. Thus users can use InnoDB without having to
|
||||
specify any startup options.
|
||||
*/
|
||||
|
||||
char *innobase_data_file_path= (char*) "ibdata1:10M:autoextend";
|
||||
static char *internal_innobase_data_file_path=0;
|
||||
static char *internal_innobase_data_file_path = NULL;
|
||||
|
||||
/* The following counter is used to convey information to InnoDB
|
||||
about server activity: in selects it is not sensible to call
|
||||
|
|
@ -652,21 +646,24 @@ innobase_init(void)
|
|||
|
||||
os_innodb_umask = (ulint)my_umask;
|
||||
|
||||
/*
|
||||
When using the embedded server, the datadirectory is not
|
||||
in the current directory.
|
||||
*/
|
||||
if (mysql_embedded)
|
||||
default_path=mysql_real_data_home;
|
||||
else
|
||||
{
|
||||
/* It's better to use current lib, to keep path's short */
|
||||
/* First calculate the default path for innodb_data_home_dir etc.,
|
||||
in case the user has not given any value.
|
||||
|
||||
Note that when using the embedded server, the datadirectory is not
|
||||
necessarily the current directory of this program. */
|
||||
|
||||
if (mysql_embedded) {
|
||||
default_path = mysql_real_data_home;
|
||||
} else {
|
||||
/* It's better to use current lib, to keep paths short */
|
||||
current_dir[0] = FN_CURLIB;
|
||||
current_dir[1] = FN_LIBCHAR;
|
||||
current_dir[2] = 0;
|
||||
default_path=current_dir;
|
||||
default_path = current_dir;
|
||||
}
|
||||
|
||||
ut_a(default_path);
|
||||
|
||||
if (specialflag & SPECIAL_NO_PRIOR) {
|
||||
srv_set_thread_priorities = FALSE;
|
||||
} else {
|
||||
|
|
@ -674,22 +671,32 @@ innobase_init(void)
|
|||
srv_query_thread_priority = QUERY_PRIOR;
|
||||
}
|
||||
|
||||
/*
|
||||
Set InnoDB initialization parameters according to the values
|
||||
read from MySQL .cnf file
|
||||
*/
|
||||
/* Set InnoDB initialization parameters according to the values
|
||||
read from MySQL .cnf file */
|
||||
|
||||
// Make a copy of innobase_data_file_path to not modify the original
|
||||
internal_innobase_data_file_path=my_strdup(innobase_data_file_path,
|
||||
MYF(MY_WME));
|
||||
/*--------------- Data files -------------------------*/
|
||||
|
||||
/* The default dir for data files is the datadir of MySQL */
|
||||
|
||||
srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
|
||||
default_path);
|
||||
srv_arch_dir = (innobase_log_arch_dir ? innobase_log_arch_dir :
|
||||
default_path);
|
||||
|
||||
ret = (bool)
|
||||
srv_parse_data_file_paths_and_sizes(internal_innobase_data_file_path,
|
||||
/* Set default InnoDB data file size to 10 MB and let it be
|
||||
auto-extending. Thus users can use InnoDB in >= 4.0 without having
|
||||
to specify any startup options. */
|
||||
|
||||
if (!innobase_data_file_path) {
|
||||
innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
|
||||
}
|
||||
|
||||
/* Since InnoDB edits the argument in the next call, we make another
|
||||
copy of it: */
|
||||
|
||||
internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
|
||||
MYF(MY_WME));
|
||||
|
||||
ret = (bool) srv_parse_data_file_paths_and_sizes(
|
||||
internal_innobase_data_file_path,
|
||||
&srv_data_file_names,
|
||||
&srv_data_file_sizes,
|
||||
&srv_data_file_is_raw_partition,
|
||||
|
|
@ -697,12 +704,26 @@ innobase_init(void)
|
|||
&srv_auto_extend_last_data_file,
|
||||
&srv_last_file_size_max);
|
||||
if (ret == FALSE) {
|
||||
sql_print_error("InnoDB: syntax error in innodb_data_file_path");
|
||||
sql_print_error(
|
||||
"InnoDB: syntax error in innodb_data_file_path");
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (!innobase_log_group_home_dir)
|
||||
innobase_log_group_home_dir= default_path;
|
||||
/* -------------- Log files ---------------------------*/
|
||||
|
||||
/* The default dir for log files is the datadir of MySQL */
|
||||
|
||||
if (!innobase_log_group_home_dir) {
|
||||
innobase_log_group_home_dir = default_path;
|
||||
}
|
||||
|
||||
/* Since innodb_log_arch_dir has no relevance under MySQL,
|
||||
starting from 4.0.6 we always set it the same as
|
||||
innodb_log_group_home_dir: */
|
||||
|
||||
innobase_log_arch_dir = innobase_log_group_home_dir;
|
||||
|
||||
srv_arch_dir = innobase_log_arch_dir;
|
||||
|
||||
ret = (bool)
|
||||
srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
|
||||
|
|
@ -716,9 +737,9 @@ innobase_init(void)
|
|||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
srv_file_flush_method_str = (innobase_unix_file_flush_method ?
|
||||
innobase_unix_file_flush_method :
|
||||
NULL);
|
||||
/* --------------------------------------------------*/
|
||||
|
||||
srv_file_flush_method_str = innobase_unix_file_flush_method;
|
||||
|
||||
srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
|
||||
srv_n_log_files = (ulint) innobase_log_files_in_group;
|
||||
|
|
@ -741,7 +762,9 @@ innobase_init(void)
|
|||
srv_fast_shutdown = (ibool) innobase_fast_shutdown;
|
||||
|
||||
srv_print_verbose_log = mysql_embedded ? 0 : 1;
|
||||
|
||||
if (strcmp(default_charset_info->name, "latin1") == 0) {
|
||||
|
||||
/* Store the character ordering table to InnoDB.
|
||||
For non-latin1 charsets we use the MySQL comparison
|
||||
functions, and consequently we do not need to know
|
||||
|
|
@ -4179,3 +4202,4 @@ ha_innobase::get_auto_increment()
|
|||
}
|
||||
|
||||
#endif /* HAVE_INNOBASE_DB */
|
||||
|
||||
|
|
|
|||
|
|
@ -883,13 +883,13 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
|
|||
void ha_key_cache(void)
|
||||
{
|
||||
if (keybuff_size)
|
||||
(void) init_key_cache(keybuff_size);
|
||||
(void) init_key_cache((ulong) keybuff_size);
|
||||
}
|
||||
|
||||
|
||||
void ha_resize_key_cache(void)
|
||||
{
|
||||
(void) resize_key_cache(keybuff_size);
|
||||
(void) resize_key_cache((ulong) keybuff_size);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
32
sql/item.cc
32
sql/item.cc
|
|
@ -701,7 +701,7 @@ void Item_field::save_org_in_field(Field *to)
|
|||
if (field->is_null())
|
||||
{
|
||||
null_value=1;
|
||||
set_field_to_null_with_conversions(to);
|
||||
set_field_to_null_with_conversions(to, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -711,12 +711,12 @@ void Item_field::save_org_in_field(Field *to)
|
|||
}
|
||||
}
|
||||
|
||||
int Item_field::save_in_field(Field *to)
|
||||
int Item_field::save_in_field(Field *to, bool no_conversions)
|
||||
{
|
||||
if (result_field->is_null())
|
||||
{
|
||||
null_value=1;
|
||||
return set_field_to_null_with_conversions(to);
|
||||
return set_field_to_null_with_conversions(to, no_conversions);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -744,9 +744,9 @@ int Item_field::save_in_field(Field *to)
|
|||
1 Field doesn't support NULL values and can't handle 'field = NULL'
|
||||
*/
|
||||
|
||||
int Item_null::save_in_field(Field *field)
|
||||
int Item_null::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
return set_field_to_null_with_conversions(field);
|
||||
return set_field_to_null_with_conversions(field, no_conversions);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -768,7 +768,7 @@ int Item_null::save_safe_in_field(Field *field)
|
|||
}
|
||||
|
||||
|
||||
int Item::save_in_field(Field *field)
|
||||
int Item::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
int error;
|
||||
if (result_type() == STRING_RESULT ||
|
||||
|
|
@ -781,7 +781,7 @@ int Item::save_in_field(Field *field)
|
|||
str_value.set_quick(buff,sizeof(buff),cs);
|
||||
result=val_str(&str_value);
|
||||
if (null_value)
|
||||
return set_field_to_null_with_conversions(field);
|
||||
return set_field_to_null_with_conversions(field, no_conversions);
|
||||
field->set_notnull();
|
||||
error=field->store(result->ptr(),result->length(),cs);
|
||||
str_value.set_quick(0, 0, cs);
|
||||
|
|
@ -798,14 +798,15 @@ int Item::save_in_field(Field *field)
|
|||
{
|
||||
longlong nr=val_int();
|
||||
if (null_value)
|
||||
return set_field_to_null_with_conversions(field);
|
||||
return set_field_to_null_with_conversions(field, no_conversions);
|
||||
field->set_notnull();
|
||||
error=field->store(nr);
|
||||
}
|
||||
return (error) ? -1 : 0;
|
||||
}
|
||||
|
||||
int Item_string::save_in_field(Field *field)
|
||||
|
||||
int Item_string::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
String *result;
|
||||
result=val_str(&str_value);
|
||||
|
|
@ -815,7 +816,8 @@ int Item_string::save_in_field(Field *field)
|
|||
return (field->store(result->ptr(),result->length(),charset())) ? -1 : 0;
|
||||
}
|
||||
|
||||
int Item_int::save_in_field(Field *field)
|
||||
|
||||
int Item_int::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
longlong nr=val_int();
|
||||
if (null_value)
|
||||
|
|
@ -824,7 +826,8 @@ int Item_int::save_in_field(Field *field)
|
|||
return (field->store(nr)) ? -1 : 0;
|
||||
}
|
||||
|
||||
int Item_real::save_in_field(Field *field)
|
||||
|
||||
int Item_real::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
double nr=val();
|
||||
if (null_value)
|
||||
|
|
@ -877,7 +880,7 @@ longlong Item_varbinary::val_int()
|
|||
}
|
||||
|
||||
|
||||
int Item_varbinary::save_in_field(Field *field)
|
||||
int Item_varbinary::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
int error;
|
||||
field->set_notnull();
|
||||
|
|
@ -1030,9 +1033,10 @@ bool Item_ref::check_loop(uint id)
|
|||
DBUG_RETURN((*ref)->check_loop(id));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** If item is a const function, calculate it and return a const item
|
||||
** The original item is freed if not returned
|
||||
If item is a const function, calculate it and return a const item
|
||||
The original item is freed if not returned
|
||||
*/
|
||||
|
||||
Item_result item_cmp_type(Item_result a,Item_result b)
|
||||
|
|
|
|||
27
sql/item.h
27
sql/item.h
|
|
@ -54,11 +54,11 @@ public:
|
|||
void set_name(const char *str,uint length=0);
|
||||
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
||||
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
virtual int save_in_field(Field *field);
|
||||
virtual int save_in_field(Field *field, bool no_conversions);
|
||||
virtual void save_org_in_field(Field *field)
|
||||
{ (void) save_in_field(field); }
|
||||
{ (void) save_in_field(field, 1); }
|
||||
virtual int save_safe_in_field(Field *field)
|
||||
{ return save_in_field(field); }
|
||||
{ return save_in_field(field, 1); }
|
||||
virtual bool send(THD *thd, String *str);
|
||||
virtual bool eq(const Item *, bool binary_cmp) const;
|
||||
virtual Item_result result_type () const { return REAL_RESULT; }
|
||||
|
|
@ -194,7 +194,7 @@ public:
|
|||
}
|
||||
void make_field(Send_field *field);
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
int save_in_field(Field *field);
|
||||
int save_in_field(Field *field,bool no_conversions);
|
||||
void save_org_in_field(Field *field);
|
||||
table_map used_tables() const;
|
||||
enum Item_result result_type () const
|
||||
|
|
@ -219,7 +219,7 @@ public:
|
|||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
void make_field(Send_field *field);
|
||||
int save_in_field(Field *field);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
int save_safe_in_field(Field *field);
|
||||
enum Item_result result_type () const
|
||||
{ return STRING_RESULT; }
|
||||
|
|
@ -289,7 +289,7 @@ public:
|
|||
double val() { return (double) value; }
|
||||
String *val_str(String*);
|
||||
void make_field(Send_field *field);
|
||||
int save_in_field(Field *field);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
bool basic_const_item() const { return 1; }
|
||||
Item *new_item() { return new Item_int(name,value,max_length); }
|
||||
void print(String *str);
|
||||
|
|
@ -329,7 +329,7 @@ public:
|
|||
max_length=length;
|
||||
}
|
||||
Item_real(double value_par) :value(value_par) {}
|
||||
int save_in_field(Field *field);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
enum Type type() const { return REAL_ITEM; }
|
||||
double val() { return value; }
|
||||
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
|
||||
|
|
@ -372,7 +372,7 @@ public:
|
|||
double val() { return atof(str_value.ptr()); }
|
||||
longlong val_int() { return strtoll(str_value.ptr(),(char**) 0,10); }
|
||||
String *val_str(String*) { return (String*) &str_value; }
|
||||
int save_in_field(Field *field);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
void make_field(Send_field *field);
|
||||
enum Item_result result_type () const { return STRING_RESULT; }
|
||||
bool basic_const_item() const { return 1; }
|
||||
|
|
@ -392,7 +392,7 @@ public:
|
|||
Item_default() { name= (char*) "DEFAULT"; }
|
||||
enum Type type() const { return DEFAULT_ITEM; }
|
||||
void make_field(Send_field *field) {}
|
||||
int save_in_field(Field *field)
|
||||
int save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
field->set_default();
|
||||
return 0;
|
||||
|
|
@ -430,7 +430,7 @@ public:
|
|||
double val() { return (double) Item_varbinary::val_int(); }
|
||||
longlong val_int();
|
||||
String *val_str(String*) { return &str_value; }
|
||||
int save_in_field(Field *field);
|
||||
int save_in_field(Field *field, bool no_conversions);
|
||||
void make_field(Send_field *field);
|
||||
enum Item_result result_type () const { return INT_RESULT; }
|
||||
};
|
||||
|
|
@ -490,7 +490,8 @@ public:
|
|||
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
|
||||
void make_field(Send_field *field) { (*ref)->make_field(field); }
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
int save_in_field(Field *field) { return (*ref)->save_in_field(field); }
|
||||
int save_in_field(Field *field, bool no_conversions)
|
||||
{ return (*ref)->save_in_field(field, no_conversions); }
|
||||
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||
table_map used_tables() const { return (*ref)->used_tables(); }
|
||||
|
|
@ -510,9 +511,9 @@ class Item_int_with_ref :public Item_int
|
|||
public:
|
||||
Item_int_with_ref(longlong i, Item *ref_arg) :Item_int(i), ref(ref_arg)
|
||||
{}
|
||||
int save_in_field(Field *field)
|
||||
int save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
return ref->save_in_field(field);
|
||||
return ref->save_in_field(field, no_conversions);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ static bool convert_constant_item(Field *field, Item **item)
|
|||
{
|
||||
if ((*item)->const_item() && (*item)->type() != Item::INT_ITEM)
|
||||
{
|
||||
if (!(*item)->save_in_field(field) && !((*item)->null_value))
|
||||
if (!(*item)->save_in_field(field, 1) && !((*item)->null_value))
|
||||
{
|
||||
Item *tmp=new Item_int_with_ref(field->val_int(), *item);
|
||||
if (tmp)
|
||||
|
|
@ -519,15 +519,29 @@ longlong Item_func_between::val_int()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static Item_result item_store_type(Item_result a,Item_result b)
|
||||
{
|
||||
if (a == STRING_RESULT || b == STRING_RESULT)
|
||||
return STRING_RESULT;
|
||||
else if (a == REAL_RESULT || b == REAL_RESULT)
|
||||
return REAL_RESULT;
|
||||
else
|
||||
return INT_RESULT;
|
||||
}
|
||||
|
||||
void
|
||||
Item_func_ifnull::fix_length_and_dec()
|
||||
{
|
||||
maybe_null=args[1]->maybe_null;
|
||||
max_length=max(args[0]->max_length,args[1]->max_length);
|
||||
decimals=max(args[0]->decimals,args[1]->decimals);
|
||||
cached_result_type=args[0]->result_type();
|
||||
if ((cached_result_type=item_store_type(args[0]->result_type(),
|
||||
args[1]->result_type())) !=
|
||||
REAL_RESULT)
|
||||
decimals= 0;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
Item_func_ifnull::val()
|
||||
{
|
||||
|
|
@ -1163,6 +1177,18 @@ void Item_func_in::update_used_tables()
|
|||
const_item_cache&=item->const_item();
|
||||
}
|
||||
|
||||
void Item_func_in::split_sum_func(List<Item> &fields)
|
||||
{
|
||||
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
|
||||
item->split_sum_func(fields);
|
||||
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
|
||||
{
|
||||
fields.push_front(item);
|
||||
item=new Item_ref((Item**) fields.head_ref(),0,item->name);
|
||||
}
|
||||
Item_func::split_sum_func(fields);
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_bit_or::val_int()
|
||||
{
|
||||
|
|
@ -1394,15 +1420,15 @@ longlong Item_cond_or::val_int()
|
|||
Item *and_expressions(Item *a, Item *b, Item **org_item)
|
||||
{
|
||||
if (!a)
|
||||
return (*org_item= b);
|
||||
return (*org_item= (Item*) b);
|
||||
if (a == *org_item)
|
||||
{
|
||||
Item_cond *res;
|
||||
if ((res= new Item_cond_and(a, b)))
|
||||
if ((res= new Item_cond_and(a, (Item*) b)))
|
||||
res->used_tables_cache= a->used_tables() | b->used_tables();
|
||||
return res;
|
||||
}
|
||||
if (((Item_cond_and*) a)->add(b))
|
||||
if (((Item_cond_and*) a)->add((Item*) b))
|
||||
return 0;
|
||||
((Item_cond_and*) a)->used_tables_cache|= b->used_tables();
|
||||
return a;
|
||||
|
|
@ -1797,7 +1823,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
|
|||
i -= u;
|
||||
}
|
||||
if (i < 0)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
register const int v = plm1 - i;
|
||||
turboShift = u - v;
|
||||
|
|
@ -1814,7 +1840,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
|
|||
}
|
||||
j += shift;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1828,7 +1854,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
|
|||
i -= u;
|
||||
}
|
||||
if (i < 0)
|
||||
return true;
|
||||
return 1;
|
||||
|
||||
register const int v = plm1 - i;
|
||||
turboShift = u - v;
|
||||
|
|
@ -1845,7 +1871,7 @@ bool Item_func_like::turboBM_matches(const char* text, int text_len) const
|
|||
}
|
||||
j += shift;
|
||||
}
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -435,9 +435,11 @@ class Item_func_in :public Item_int_func
|
|||
longlong val_int();
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
|
||||
{
|
||||
return (item->check_cols(1) ||
|
||||
bool res=(item->check_cols(1) ||
|
||||
item->fix_fields(thd, tlist, &item) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
with_sum_func= with_sum_func || item->with_sum_func;
|
||||
return res;
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
~Item_func_in() { delete item; delete array; delete in_item; }
|
||||
|
|
@ -448,6 +450,7 @@ class Item_func_in :public Item_int_func
|
|||
enum Functype functype() const { return IN_FUNC; }
|
||||
const char *func_name() const { return " IN "; }
|
||||
void update_used_tables();
|
||||
void split_sum_func(List<Item> &fields);
|
||||
bool check_loop(uint id)
|
||||
{
|
||||
DBUG_ENTER("Item_func_in::check_loop");
|
||||
|
|
|
|||
|
|
@ -779,21 +779,20 @@ double Item_func_round::val()
|
|||
}
|
||||
|
||||
|
||||
double Item_func_rand::val()
|
||||
void Item_func_rand::fix_length_and_dec()
|
||||
{
|
||||
THD* thd = current_thd;
|
||||
decimals=NOT_FIXED_DEC;
|
||||
max_length=float_length(decimals);
|
||||
if (arg_count)
|
||||
{ // Only use argument once in query
|
||||
uint32 tmp= (uint32) (args[0]->val_int());
|
||||
randominit(&thd->rand,(uint32) (tmp*0x10001L+55555555L),
|
||||
if ((rand= (struct rand_struct*) sql_alloc(sizeof(*rand))))
|
||||
randominit(rand,(uint32) (tmp*0x10001L+55555555L),
|
||||
(uint32) (tmp*0x10000001L));
|
||||
#ifdef DELETE_ITEMS
|
||||
delete args[0];
|
||||
#endif
|
||||
arg_count=0;
|
||||
}
|
||||
else if (!thd->rand_used)
|
||||
else
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
/*
|
||||
No need to send a Rand log event if seed was given eg: RAND(seed),
|
||||
as it will be replicated in the query as such.
|
||||
|
|
@ -805,8 +804,14 @@ double Item_func_rand::val()
|
|||
thd->rand_used=1;
|
||||
thd->rand_saved_seed1=thd->rand.seed1;
|
||||
thd->rand_saved_seed2=thd->rand.seed2;
|
||||
rand= &thd->rand;
|
||||
}
|
||||
return rnd(&thd->rand);
|
||||
}
|
||||
|
||||
|
||||
double Item_func_rand::val()
|
||||
{
|
||||
return rnd(rand);
|
||||
}
|
||||
|
||||
longlong Item_func_sign::val_int()
|
||||
|
|
|
|||
|
|
@ -522,14 +522,15 @@ public:
|
|||
|
||||
class Item_func_rand :public Item_real_func
|
||||
{
|
||||
struct rand_struct *rand;
|
||||
public:
|
||||
Item_func_rand(Item *a) :Item_real_func(a) {}
|
||||
Item_func_rand() :Item_real_func() {}
|
||||
double val();
|
||||
const char *func_name() const { return "rand"; }
|
||||
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
|
||||
bool const_item() const { return 0; }
|
||||
table_map used_tables() const { return RAND_TABLE_BIT; }
|
||||
void fix_length_and_dec();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@ String *Item_date::val_str(String *str)
|
|||
}
|
||||
|
||||
|
||||
int Item_date::save_in_field(Field *field)
|
||||
int Item_date::save_in_field(Field *field, bool no_conversions)
|
||||
{
|
||||
TIME ltime;
|
||||
timestamp_type t_type=TIMESTAMP_FULL;
|
||||
|
|
@ -567,7 +567,7 @@ bool Item_func_now::get_date(TIME *res,
|
|||
}
|
||||
|
||||
|
||||
int Item_func_now::save_in_field(Field *to)
|
||||
int Item_func_now::save_in_field(Field *to, bool no_conversions)
|
||||
{
|
||||
to->set_notnull();
|
||||
to->store_time(<ime,TIMESTAMP_FULL);
|
||||
|
|
|
|||
|
|
@ -325,7 +325,7 @@ public:
|
|||
decimals=0;
|
||||
max_length=10*thd_charset()->mbmaxlen;
|
||||
}
|
||||
int save_in_field(Field *to);
|
||||
int save_in_field(Field *to, bool no_conversions);
|
||||
void make_field(Send_field *tmp_field)
|
||||
{
|
||||
init_make_field(tmp_field,FIELD_TYPE_DATE);
|
||||
|
|
@ -406,7 +406,7 @@ public:
|
|||
enum Item_result result_type () const { return STRING_RESULT; }
|
||||
double val() { return (double) value; }
|
||||
longlong val_int() { return value; }
|
||||
int save_in_field(Field *to);
|
||||
int save_in_field(Field *to, bool no_conversions);
|
||||
String *val_str(String *str);
|
||||
const char *func_name() const { return "now"; }
|
||||
void fix_length_and_dec();
|
||||
|
|
|
|||
24
sql/log.cc
24
sql/log.cc
|
|
@ -1062,41 +1062,45 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||
No check for auto events flag here - this write method should
|
||||
never be called if auto-events are enabled
|
||||
*/
|
||||
if (thd && thd->last_insert_id_used)
|
||||
if (thd)
|
||||
{
|
||||
Intvar_log_event e(thd,(uchar)LAST_INSERT_ID_EVENT,thd->last_insert_id);
|
||||
if (thd->last_insert_id_used)
|
||||
{
|
||||
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
|
||||
thd->last_insert_id);
|
||||
e.set_log_pos(this);
|
||||
if (thd->server_id)
|
||||
e.server_id = thd->server_id;
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
if (thd && thd->insert_id_used)
|
||||
if (thd->insert_id_used)
|
||||
{
|
||||
Intvar_log_event e(thd,(uchar)INSERT_ID_EVENT,thd->last_insert_id);
|
||||
Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id);
|
||||
e.set_log_pos(this);
|
||||
if (thd->server_id)
|
||||
e.server_id = thd->server_id;
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
if (thd && thd->rand_used)
|
||||
if (thd->rand_used)
|
||||
{
|
||||
Rand_log_event e(thd,thd->rand_saved_seed1,thd->rand_saved_seed2);
|
||||
e.set_log_pos(this);
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
if (thd && thd->variables.convert_set)
|
||||
if (thd->variables.convert_set)
|
||||
{
|
||||
char buf[1024] = "SET CHARACTER SET ";
|
||||
char* p = strend(buf);
|
||||
p = strmov(p, thd->variables.convert_set->name);
|
||||
Query_log_event e(thd, buf, (ulong)(p - buf), 0);
|
||||
char buf[256], *p;
|
||||
p= strmov(strmov(buf, "SET CHARACTER SET "),
|
||||
thd->variables.convert_set->name);
|
||||
Query_log_event e(thd, buf, (ulong) (p - buf), 0);
|
||||
e.set_log_pos(this);
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
event_info->set_log_pos(this);
|
||||
if (event_info->write(file) ||
|
||||
file == &log_file && flush_io_cache(file))
|
||||
|
|
|
|||
|
|
@ -249,6 +249,20 @@ typedef struct st_sql_list {
|
|||
uint elements;
|
||||
byte *first;
|
||||
byte **next;
|
||||
|
||||
inline void empty()
|
||||
{
|
||||
elements=0;
|
||||
first=0;
|
||||
next= &first;
|
||||
}
|
||||
inline void link_in_list(byte *element,byte **next_ptr)
|
||||
{
|
||||
elements++;
|
||||
(*next)=element;
|
||||
next= next_ptr;
|
||||
*next=0;
|
||||
}
|
||||
} SQL_LIST;
|
||||
|
||||
|
||||
|
|
@ -443,6 +457,10 @@ int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
|||
List<Item> &values,COND *conds,
|
||||
ORDER *order, ha_rows limit,
|
||||
enum enum_duplicates handle_duplicates);
|
||||
int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
|
||||
List<Item> *fields, List<Item> *values,
|
||||
COND *conds, ulong options,
|
||||
enum enum_duplicates handle_duplicates);
|
||||
int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
|
||||
List<List_item> &values, List<Item> &update_fields,
|
||||
List<Item> &update_values, enum_duplicates flag);
|
||||
|
|
@ -545,7 +563,7 @@ void store_position_for_column(const char *name);
|
|||
bool add_to_list(SQL_LIST &list,Item *group,bool asc=0);
|
||||
void add_join_on(TABLE_LIST *b,Item *expr);
|
||||
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
|
||||
bool add_proc_to_list(Item *item);
|
||||
bool add_proc_to_list(THD *thd, Item *item);
|
||||
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
|
||||
|
||||
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
|
||||
|
|
@ -664,6 +682,7 @@ extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
|||
extern char pidfile_name[FN_REFLEN], time_zone[30], *opt_init_file;
|
||||
extern char blob_newline;
|
||||
extern double log_10[32];
|
||||
extern ulonglong keybuff_size;
|
||||
extern ulong refresh_version,flush_version, thread_id,query_id,opened_tables;
|
||||
extern ulong created_tmp_tables, created_tmp_disk_tables;
|
||||
extern ulong aborted_threads,aborted_connects;
|
||||
|
|
@ -682,8 +701,7 @@ extern ulong ha_read_count, ha_write_count, ha_delete_count, ha_update_count;
|
|||
extern ulong ha_read_key_count, ha_read_next_count, ha_read_prev_count;
|
||||
extern ulong ha_read_first_count, ha_read_last_count;
|
||||
extern ulong ha_read_rnd_count, ha_read_rnd_next_count;
|
||||
extern ulong ha_commit_count, ha_rollback_count;
|
||||
extern ulong keybuff_size,table_cache_size;
|
||||
extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
|
||||
extern ulong max_connections,max_connect_errors, connect_timeout;
|
||||
extern ulong max_insert_delayed_threads, max_user_connections;
|
||||
extern ulong long_query_count, what_to_log,flush_time,opt_sql_mode;
|
||||
|
|
@ -732,6 +750,7 @@ extern SHOW_COMP_OPTION have_innodb;
|
|||
extern SHOW_COMP_OPTION have_berkeley_db;
|
||||
extern struct system_variables global_system_variables;
|
||||
extern struct system_variables max_system_variables;
|
||||
extern struct rand_struct sql_rand;
|
||||
|
||||
/* optional things, have_* variables */
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include <nisam.h>
|
||||
#include <thr_alarm.h>
|
||||
#include <ft_global.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef DBUG_OFF
|
||||
#define ONE_THREAD
|
||||
|
|
@ -322,7 +323,8 @@ ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
|
|||
uint protocol_version=PROTOCOL_VERSION;
|
||||
struct system_variables global_system_variables;
|
||||
struct system_variables max_system_variables;
|
||||
ulong keybuff_size,table_cache_size,
|
||||
ulonglong keybuff_size;
|
||||
ulong table_cache_size,
|
||||
thread_stack,
|
||||
thread_stack_min,what_to_log= ~ (1L << (uint) COM_TIME),
|
||||
query_buff_size,
|
||||
|
|
@ -451,7 +453,7 @@ pthread_attr_t connection_attrib;
|
|||
#include <process.h>
|
||||
#if !defined(EMBEDDED_LIBRARY)
|
||||
HANDLE hEventShutdown;
|
||||
static char *event_name;
|
||||
static char shutdown_event_name[40];
|
||||
#include "nt_servc.h"
|
||||
static NTService Service; // Service object for WinNT
|
||||
#endif
|
||||
|
|
@ -1019,6 +1021,7 @@ static void set_root(const char *path)
|
|||
sql_perror("chroot");
|
||||
unireg_abort(1);
|
||||
}
|
||||
my_setwd("/", MYF(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1391,7 +1394,7 @@ or misconfigured. This error can also be caused by malfunctioning hardware.\n",
|
|||
We will try our best to scrape up some info that will hopefully help diagnose\n\
|
||||
the problem, but since we have already crashed, something is definitely wrong\n\
|
||||
and this may fail.\n\n");
|
||||
fprintf(stderr, "key_buffer_size=%ld\n", keybuff_size);
|
||||
fprintf(stderr, "key_buffer_size=%lu\n", (ulong) keybuff_size);
|
||||
fprintf(stderr, "read_buffer_size=%ld\n", global_system_variables.read_buff_size);
|
||||
fprintf(stderr, "sort_buffer_size=%ld\n", thd->variables.sortbuff_size);
|
||||
fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
|
||||
|
|
@ -1399,7 +1402,8 @@ and this may fail.\n\n");
|
|||
fprintf(stderr, "threads_connected=%d\n", thread_count);
|
||||
fprintf(stderr, "It is possible that mysqld could use up to \n\
|
||||
key_buffer_size + (read_buffer_size + sort_buffer_size)*max_connections = %ld K\n\
|
||||
bytes of memory\n", (keybuff_size + (global_system_variables.read_buff_size +
|
||||
bytes of memory\n", ((ulong) keybuff_size +
|
||||
(global_system_variables.read_buff_size +
|
||||
thd->variables.sortbuff_size) *
|
||||
max_connections)/ 1024);
|
||||
fprintf(stderr, "Hope that's ok; if not, decrease some variables in the equation.\n\n");
|
||||
|
|
@ -2102,6 +2106,7 @@ int main(int argc, char **argv)
|
|||
(void) grant_init((THD*) 0);
|
||||
init_max_user_conn();
|
||||
init_update_queries();
|
||||
DBUG_ASSERT(current_thd == 0);
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
if (!opt_noacl)
|
||||
|
|
@ -2110,6 +2115,7 @@ int main(int argc, char **argv)
|
|||
/* init_slave() must be called after the thread keys are created */
|
||||
init_slave();
|
||||
|
||||
DBUG_ASSERT(current_thd == 0);
|
||||
if (opt_bin_log && !server_id)
|
||||
{
|
||||
server_id= !master_host ? 1 : 2;
|
||||
|
|
@ -2346,6 +2352,14 @@ bool default_service_handling(char **argv,
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
/* When several instances are running on the same machine, we
|
||||
need to have an unique named hEventShudown through the
|
||||
application PID e.g.: MySQLShutdown1890; MySQLShutdown2342
|
||||
*/
|
||||
int2str((int) GetCurrentProcessId(),strmov(shutdown_event_name,
|
||||
"MySQLShutdown"), 10);
|
||||
|
||||
if (Service.GetOS()) /* true NT family */
|
||||
{
|
||||
char file_path[FN_REFLEN];
|
||||
|
|
@ -2360,10 +2374,9 @@ int main(int argc, char **argv)
|
|||
if (Service.IsService(argv[1]))
|
||||
{
|
||||
/* start an optional service */
|
||||
event_name= argv[1];
|
||||
load_default_groups[0]= argv[1];
|
||||
start_mode= 1;
|
||||
Service.Init(event_name, mysql_service);
|
||||
Service.Init(argv[1], mysql_service);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -2382,9 +2395,8 @@ int main(int argc, char **argv)
|
|||
use_opt_args=1;
|
||||
opt_argc=argc;
|
||||
opt_argv=argv;
|
||||
event_name= argv[2];
|
||||
start_mode= 1;
|
||||
Service.Init(event_name, mysql_service);
|
||||
Service.Init(argv[2], mysql_service);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -2404,7 +2416,6 @@ int main(int argc, char **argv)
|
|||
{
|
||||
/* start the default service */
|
||||
start_mode= 1;
|
||||
event_name= "MySqlShutdown";
|
||||
Service.Init(MYSQL_SERVICENAME, mysql_service);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -3764,8 +3775,9 @@ struct my_option my_long_options[] =
|
|||
IO_SIZE, 0},
|
||||
{"key_buffer_size", OPT_KEY_BUFFER_SIZE,
|
||||
"The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
|
||||
(gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULONG, REQUIRED_ARG,
|
||||
KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE, 0},
|
||||
(gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL,
|
||||
REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
|
||||
IO_SIZE, 0},
|
||||
{"long_query_time", OPT_LONG_QUERY_TIME,
|
||||
"Log all queries that have taken more than long_query_time seconds to execute to file.",
|
||||
(gptr*) &global_system_variables.long_query_time,
|
||||
|
|
@ -4268,6 +4280,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||
break;
|
||||
case 'h':
|
||||
strmake(mysql_real_data_home,argument, sizeof(mysql_real_data_home)-1);
|
||||
/* Correct pointer set by my_getopt (for embedded library) */
|
||||
mysql_data_home= mysql_real_data_home;
|
||||
break;
|
||||
case 'L':
|
||||
strmake(language, argument, sizeof(language)-1);
|
||||
|
|
|
|||
|
|
@ -1019,7 +1019,7 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
|
|||
field->cmp_type() != value->result_type())
|
||||
DBUG_RETURN(0);
|
||||
|
||||
if (value->save_in_field(field) > 0)
|
||||
if (value->save_in_field(field, 1) > 0)
|
||||
{
|
||||
/* This happens when we try to insert a NULL field in a not null column */
|
||||
// TODO; Check if we can we remove the following block.
|
||||
|
|
@ -1028,9 +1028,9 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
|
|||
/* convert column_name <=> NULL -> column_name IS NULL */
|
||||
// Get local copy of key
|
||||
char *str= (char*) alloc_root(param->mem_root,1);
|
||||
if (!*str)
|
||||
if (!str)
|
||||
DBUG_RETURN(0);
|
||||
*str = 1;
|
||||
*str= 1;
|
||||
DBUG_RETURN(new SEL_ARG(field,str,str));
|
||||
}
|
||||
DBUG_RETURN(&null_element); // cmp with NULL is never true
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ sys_var_thd_ulong sys_interactive_timeout("interactive_timeout",
|
|||
&SV::net_interactive_timeout);
|
||||
sys_var_thd_ulong sys_join_buffer_size("join_buffer_size",
|
||||
&SV::join_buff_size);
|
||||
sys_var_long_ptr sys_key_buffer_size("key_buffer_size",
|
||||
sys_var_ulonglong_ptr sys_key_buffer_size("key_buffer_size",
|
||||
&keybuff_size,
|
||||
fix_key_buffer_size);
|
||||
sys_var_bool_ptr sys_local_infile("local_infile",
|
||||
|
|
@ -693,6 +693,23 @@ void sys_var_long_ptr::set_default(THD *thd, enum_var_type type)
|
|||
}
|
||||
|
||||
|
||||
bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
|
||||
{
|
||||
ulonglong tmp= var->value->val_int();
|
||||
if (option_limits)
|
||||
*value= (ulonglong) getopt_ull_limit_value(tmp, option_limits);
|
||||
else
|
||||
*value= (ulonglong) tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sys_var_ulonglong_ptr::set_default(THD *thd, enum_var_type type)
|
||||
{
|
||||
*value= (ulonglong) option_limits->def_value;
|
||||
}
|
||||
|
||||
|
||||
bool sys_var_bool_ptr::update(THD *thd, set_var *var)
|
||||
{
|
||||
*value= (my_bool) var->save_result.ulong_value;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,22 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class sys_var_ulonglong_ptr :public sys_var
|
||||
{
|
||||
public:
|
||||
ulonglong *value;
|
||||
sys_var_ulonglong_ptr(const char *name_arg, ulonglong *value_ptr)
|
||||
:sys_var(name_arg),value(value_ptr) {}
|
||||
sys_var_ulonglong_ptr(const char *name_arg, ulonglong *value_ptr,
|
||||
sys_after_update_func func)
|
||||
:sys_var(name_arg,func), value(value_ptr) {}
|
||||
bool update(THD *thd, set_var *var);
|
||||
void set_default(THD *thd, enum_var_type type);
|
||||
SHOW_TYPE type() { return SHOW_LONGLONG; }
|
||||
byte *value_ptr(THD *thd, enum_var_type type) { return (byte*) value; }
|
||||
};
|
||||
|
||||
|
||||
class sys_var_bool_ptr :public sys_var
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -2224,8 +2224,8 @@ static key_map get_key_map_from_key_list(TABLE *table,
|
|||
}
|
||||
|
||||
/****************************************************************************
|
||||
** This just drops in all fields instead of current '*' field
|
||||
** Returns pointer to last inserted field if ok
|
||||
This just drops in all fields instead of current '*' field
|
||||
Returns pointer to last inserted field if ok
|
||||
****************************************************************************/
|
||||
|
||||
bool
|
||||
|
|
@ -2239,21 +2239,26 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
|
|||
for (; tables ; tables=tables->next)
|
||||
{
|
||||
TABLE *table=tables->table;
|
||||
if (grant_option && !thd->master_access &&
|
||||
check_grant_all_columns(thd,SELECT_ACL,table) )
|
||||
DBUG_RETURN(-1);
|
||||
if (!table_name || (!strcmp(table_name,tables->alias) &&
|
||||
(!db_name || !strcmp(tables->db,db_name))))
|
||||
{
|
||||
/* Ensure that we have access right to all columns */
|
||||
if (grant_option && !thd->master_access &&
|
||||
check_grant_all_columns(thd,SELECT_ACL,table) )
|
||||
DBUG_RETURN(-1);
|
||||
Field **ptr=table->field,*field;
|
||||
thd->used_tables|=table->map;
|
||||
while ((field = *ptr++))
|
||||
{
|
||||
Item_field *item= new Item_field(field);
|
||||
if (!found++)
|
||||
(void) it->replace(item);
|
||||
(void) it->replace(item); // Replace '*'
|
||||
else
|
||||
it->after(item);
|
||||
/*
|
||||
Mark if field used before in this select.
|
||||
Used by 'insert' to verify if a field name is used twice
|
||||
*/
|
||||
if (field->query_id == thd->query_id)
|
||||
thd->dupp_field=field;
|
||||
field->query_id=thd->query_id;
|
||||
|
|
@ -2377,7 +2382,7 @@ fill_record(List<Item> &fields,List<Item> &values)
|
|||
while ((field=(Item_field*) f++))
|
||||
{
|
||||
value=v++;
|
||||
if (value->save_in_field(field->field) > 0)
|
||||
if (value->save_in_field(field->field, 0) > 0)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
|
@ -2395,7 +2400,7 @@ fill_record(Field **ptr,List<Item> &values)
|
|||
while ((field = *ptr++))
|
||||
{
|
||||
value=v++;
|
||||
if (value->save_in_field(field) == 1)
|
||||
if (value->save_in_field(field, 0) == 1)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@
|
|||
#include <mysys_err.h>
|
||||
#include <assert.h>
|
||||
|
||||
extern struct rand_struct sql_rand;
|
||||
|
||||
/*****************************************************************************
|
||||
** Instansiate templates
|
||||
|
|
@ -172,9 +171,8 @@ THD::THD():user_time(0), fatal_error(0),
|
|||
{
|
||||
pthread_mutex_lock(&LOCK_thread_count);
|
||||
ulong tmp=(ulong) (rnd(&sql_rand) * 3000000);
|
||||
randominit(&rand, tmp + (ulong) start_time,
|
||||
tmp + (ulong) thread_id);
|
||||
pthread_mutex_unlock(&LOCK_thread_count);
|
||||
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -679,7 +679,7 @@ public:
|
|||
}
|
||||
virtual bool send_fields(List<Item> &list,uint flag)=0;
|
||||
virtual bool send_data(List<Item> &items)=0;
|
||||
virtual void initialize_tables (JOIN *join=0) {}
|
||||
virtual bool initialize_tables (JOIN *join=0) { return 0; }
|
||||
virtual void send_error(uint errcode,const char *err)
|
||||
{
|
||||
my_message(errcode, err, MYF(0));
|
||||
|
|
@ -743,10 +743,10 @@ class select_insert :public select_result {
|
|||
List<Item> *fields;
|
||||
ulonglong last_insert_id;
|
||||
COPY_INFO info;
|
||||
uint save_time_stamp;
|
||||
|
||||
select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic)
|
||||
:table(table_par),fields(fields_par), last_insert_id(0), save_time_stamp(0) {
|
||||
:table(table_par),fields(fields_par), last_insert_id(0)
|
||||
{
|
||||
bzero((char*) &info,sizeof(info));
|
||||
info.handle_duplicates=duplic;
|
||||
}
|
||||
|
|
@ -790,8 +790,8 @@ class select_union :public select_result {
|
|||
public:
|
||||
TABLE *table;
|
||||
COPY_INFO info;
|
||||
uint save_time_stamp;
|
||||
TMP_TABLE_PARAM *tmp_table_param;
|
||||
bool not_describe;
|
||||
|
||||
select_union(TABLE *table_par);
|
||||
~select_union();
|
||||
|
|
@ -923,7 +923,8 @@ public:
|
|||
friend int unique_write_to_ptrs(gptr key, element_count count, Unique *unique);
|
||||
};
|
||||
|
||||
class multi_delete : public select_result {
|
||||
class multi_delete : public select_result
|
||||
{
|
||||
TABLE_LIST *delete_tables, *table_being_deleted;
|
||||
#ifdef SINISAS_STRIP
|
||||
IO_CACHE **tempfiles;
|
||||
|
|
@ -936,45 +937,47 @@ public:
|
|||
uint num_of_tables;
|
||||
int error;
|
||||
bool do_delete, transactional_tables, log_delayed, normal_tables;
|
||||
public:
|
||||
public:
|
||||
multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
|
||||
~multi_delete();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
void initialize_tables (JOIN *join);
|
||||
bool initialize_tables (JOIN *join);
|
||||
void send_error(uint errcode,const char *err);
|
||||
int do_deletes (bool from_send_error);
|
||||
bool send_eof();
|
||||
};
|
||||
};
|
||||
|
||||
class multi_update : public select_result {
|
||||
TABLE_LIST *update_tables, *table_being_updated;
|
||||
COPY_INFO *infos;
|
||||
TABLE **tmp_tables;
|
||||
|
||||
class multi_update : public select_result
|
||||
{
|
||||
TABLE_LIST *all_tables, *update_tables, *table_being_updated;
|
||||
THD *thd;
|
||||
TABLE **tmp_tables, *main_table;
|
||||
TMP_TABLE_PARAM *tmp_table_param;
|
||||
ha_rows updated, found;
|
||||
List<Item> fields;
|
||||
List <Item> **fields_by_tables;
|
||||
enum enum_duplicates dupl;
|
||||
uint num_of_tables, num_fields, num_updated, *save_time_stamps, *field_sequence;
|
||||
int error;
|
||||
bool do_update, not_trans_safe;
|
||||
public:
|
||||
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
uint num);
|
||||
List <Item> *fields, *values;
|
||||
List <Item> **fields_for_table, **values_for_table;
|
||||
uint table_count;
|
||||
Copy_field *copy_field;
|
||||
enum enum_duplicates handle_duplicates;
|
||||
bool do_update, trans_safe, transactional_tables, log_delayed;
|
||||
|
||||
public:
|
||||
multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> *fields,
|
||||
List<Item> *values, enum_duplicates handle_duplicates);
|
||||
~multi_update();
|
||||
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
|
||||
bool send_fields(List<Item> &list,
|
||||
uint flag) { return 0; }
|
||||
bool send_fields(List<Item> &list, uint flag) { return 0; }
|
||||
bool send_data(List<Item> &items);
|
||||
void initialize_tables (JOIN *join);
|
||||
bool initialize_tables (JOIN *join);
|
||||
void send_error(uint errcode,const char *err);
|
||||
int do_updates (bool from_send_error);
|
||||
bool send_eof();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
class select_dumpvar :public select_result {
|
||||
ha_rows row_count;
|
||||
|
|
|
|||
|
|
@ -226,12 +226,13 @@ cleanup:
|
|||
|
||||
extern "C" int refposcmp2(void* arg, const void *a,const void *b)
|
||||
{
|
||||
/* arg is a pointer to file->ref_length */
|
||||
return memcmp(a,b, *(int*) arg);
|
||||
}
|
||||
|
||||
multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
|
||||
uint num_of_tables_arg)
|
||||
: delete_tables (dt), thd(thd_arg), deleted(0),
|
||||
: delete_tables(dt), thd(thd_arg), deleted(0),
|
||||
num_of_tables(num_of_tables_arg), error(0),
|
||||
do_delete(0), transactional_tables(0), log_delayed(0), normal_tables(0)
|
||||
{
|
||||
|
|
@ -244,31 +245,22 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
{
|
||||
DBUG_ENTER("multi_delete::prepare");
|
||||
unit= u;
|
||||
do_delete = true;
|
||||
do_delete= 1;
|
||||
thd->proc_info="deleting from main table";
|
||||
|
||||
if (thd->options & OPTION_SAFE_UPDATES)
|
||||
{
|
||||
TABLE_LIST *table_ref;
|
||||
for (table_ref=delete_tables; table_ref; table_ref=table_ref->next)
|
||||
{
|
||||
TABLE *table=table_ref->table;
|
||||
if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
|
||||
{
|
||||
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
bool
|
||||
multi_delete::initialize_tables(JOIN *join)
|
||||
{
|
||||
int counter=0;
|
||||
TABLE_LIST *walk;
|
||||
Unique **tempfiles_ptr;
|
||||
DBUG_ENTER("initialize_tables");
|
||||
|
||||
if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
table_map tables_to_delete_from=0;
|
||||
for (walk= delete_tables ; walk ; walk=walk->next)
|
||||
tables_to_delete_from|= walk->table->map;
|
||||
|
|
@ -282,9 +274,10 @@ multi_delete::initialize_tables(JOIN *join)
|
|||
{
|
||||
/* We are going to delete from this table */
|
||||
TABLE *tbl=walk->table=tab->table;
|
||||
walk=walk->next;
|
||||
/* Don't use KEYREAD optimization on this table */
|
||||
tbl->no_keyread=1;
|
||||
walk=walk->next;
|
||||
tbl->used_keys= 0;
|
||||
if (tbl->file->has_transactions())
|
||||
log_delayed= transactional_tables= 1;
|
||||
else if (tbl->tmp_table != NO_TMP_TABLE)
|
||||
|
|
@ -294,19 +287,17 @@ multi_delete::initialize_tables(JOIN *join)
|
|||
}
|
||||
}
|
||||
walk= delete_tables;
|
||||
walk->table->used_keys=0;
|
||||
for (walk=walk->next ; walk ; walk=walk->next, counter++)
|
||||
tempfiles_ptr= tempfiles;
|
||||
for (walk=walk->next ; walk ; walk=walk->next)
|
||||
{
|
||||
tables_to_delete_from|= walk->table->map;
|
||||
TABLE *table=walk->table;
|
||||
/* Don't use key read with MULTI-TABLE-DELETE */
|
||||
table->used_keys=0;
|
||||
tempfiles[counter] = new Unique (refposcmp2,
|
||||
*tempfiles_ptr++= new Unique (refposcmp2,
|
||||
(void *) &table->file->ref_length,
|
||||
table->file->ref_length,
|
||||
MEM_STRIP_BUF_SIZE);
|
||||
}
|
||||
init_ftfuncs(thd, thd->lex.current_select->select_lex(), 1);
|
||||
DBUG_RETURN(thd->fatal_error != 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -321,7 +312,7 @@ multi_delete::~multi_delete()
|
|||
t->no_keyread=0;
|
||||
}
|
||||
|
||||
for (uint counter = 0; counter < num_of_tables-1; counter++)
|
||||
for (uint counter= 0; counter < num_of_tables-1; counter++)
|
||||
{
|
||||
if (tempfiles[counter])
|
||||
delete tempfiles[counter];
|
||||
|
|
@ -428,7 +419,7 @@ int multi_delete::do_deletes(bool from_send_error)
|
|||
else
|
||||
table_being_deleted = delete_tables;
|
||||
|
||||
do_delete = false;
|
||||
do_delete= 0;
|
||||
for (table_being_deleted=table_being_deleted->next;
|
||||
table_being_deleted ;
|
||||
table_being_deleted=table_being_deleted->next, counter++)
|
||||
|
|
@ -483,7 +474,7 @@ bool multi_delete::send_eof()
|
|||
was a non-transaction-safe table involved, since
|
||||
modifications in it cannot be rolled back.
|
||||
*/
|
||||
if (deleted)
|
||||
if (deleted && (error <= 0 || normal_tables))
|
||||
{
|
||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||
if (mysql_bin_log.is_open())
|
||||
|
|
@ -493,11 +484,17 @@ bool multi_delete::send_eof()
|
|||
if (mysql_bin_log.write(&qinfo) && !normal_tables)
|
||||
local_error=1; // Log write failed: roll back the SQL statement
|
||||
}
|
||||
/* Commit or rollback the current SQL statement */
|
||||
VOID(ha_autocommit_or_rollback(thd,local_error > 0));
|
||||
|
||||
query_cache_invalidate3(thd, delete_tables, 1);
|
||||
if (!log_delayed)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
/* Commit or rollback the current SQL statement */
|
||||
if (transactional_tables)
|
||||
if (ha_autocommit_or_rollback(thd,local_error > 0))
|
||||
local_error=1;
|
||||
|
||||
if (deleted)
|
||||
query_cache_invalidate3(thd, delete_tables, 1);
|
||||
|
||||
if (local_error)
|
||||
::send_error(thd);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -180,10 +180,10 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|||
Item *item;
|
||||
for (key_len=0 ; (item=it_ke++) ; key_part++)
|
||||
{
|
||||
(void) item->save_in_field(key_part->field);
|
||||
(void) item->save_in_field(key_part->field, 1);
|
||||
key_len+=key_part->store_length;
|
||||
}
|
||||
if (!(key= (byte*) sql_calloc(ALIGN_SIZE(key_len))))
|
||||
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
|
||||
{
|
||||
send_error(thd,ER_OUTOFMEMORY);
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ static void unlink_blobs(register TABLE *table);
|
|||
|
||||
/*
|
||||
Check if insert fields are correct
|
||||
Resets form->time_stamp if a timestamp value is set
|
||||
Updates table->time_stamp to point to timestamp field or 0, depending on
|
||||
if timestamp should be updated or not.
|
||||
*/
|
||||
|
||||
int
|
||||
|
|
@ -87,9 +88,10 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
|
|||
my_error(ER_FIELD_SPECIFIED_TWICE,MYF(0), thd->dupp_field->field_name);
|
||||
return -1;
|
||||
}
|
||||
table->time_stamp=0;
|
||||
if (table->timestamp_field && // Don't set timestamp if used
|
||||
table->timestamp_field->query_id == thd->query_id)
|
||||
table->time_stamp=0; // This should be saved
|
||||
table->timestamp_field->query_id != thd->query_id)
|
||||
table->time_stamp= table->timestamp_field->offset()+1;
|
||||
}
|
||||
// For the values we need select_priv
|
||||
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
|
||||
|
|
@ -109,7 +111,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
!(thd->master_access & SUPER_ACL));
|
||||
bool transactional_table, log_delayed, bulk_insert=0;
|
||||
uint value_count;
|
||||
uint save_time_stamp;
|
||||
ulong counter = 1;
|
||||
ulonglong id;
|
||||
COPY_INFO info;
|
||||
|
|
@ -167,7 +168,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
table= table_list->table;
|
||||
thd->proc_info="init";
|
||||
thd->used_tables=0;
|
||||
save_time_stamp=table->time_stamp;
|
||||
values= its++;
|
||||
if (check_insert_fields(thd,table,fields,*values,1) ||
|
||||
setup_tables(insert_table_list) ||
|
||||
|
|
@ -175,10 +175,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
(duplic == DUP_UPDATE &&
|
||||
(setup_fields(thd, insert_table_list, update_fields, 0, 0, 0) ||
|
||||
setup_fields(thd, insert_table_list, update_values, 0, 0, 0))))
|
||||
{
|
||||
table->time_stamp= save_time_stamp;
|
||||
goto abort;
|
||||
}
|
||||
if (find_real_table_in_list(table_list->next,
|
||||
table_list->db, table_list->real_name))
|
||||
{
|
||||
|
|
@ -195,15 +192,11 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
|
||||
ER(ER_WRONG_VALUE_COUNT_ON_ROW),
|
||||
MYF(0),counter);
|
||||
table->time_stamp=save_time_stamp;
|
||||
goto abort;
|
||||
}
|
||||
if (setup_fields(thd,insert_table_list,*values,0,0,0))
|
||||
{
|
||||
table->time_stamp= save_time_stamp;
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
its.rewind ();
|
||||
/*
|
||||
Fill in the given fields and dump it to the table file
|
||||
|
|
@ -364,7 +357,6 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
}
|
||||
}
|
||||
thd->proc_info="end";
|
||||
table->time_stamp=save_time_stamp; // Restore auto timestamp ptr
|
||||
table->next_number_field=0;
|
||||
thd->count_cuted_fields=0;
|
||||
thd->next_insert_id=0; // Reset this if wrongly used
|
||||
|
|
@ -1339,7 +1331,6 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
DBUG_ENTER("select_insert::prepare");
|
||||
|
||||
unit= u;
|
||||
save_time_stamp=table->time_stamp;
|
||||
if (check_insert_fields(thd,table,*fields,values,1))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
|
|
@ -1360,8 +1351,6 @@ select_insert::~select_insert()
|
|||
{
|
||||
if (table)
|
||||
{
|
||||
if (save_time_stamp)
|
||||
table->time_stamp=save_time_stamp;
|
||||
table->next_number_field=0;
|
||||
table->file->extra(HA_EXTRA_RESET);
|
||||
}
|
||||
|
|
@ -1467,7 +1456,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
/* First field to copy */
|
||||
field=table->field+table->fields - values.elements;
|
||||
|
||||
save_time_stamp=table->time_stamp;
|
||||
if (table->timestamp_field) // Don't set timestamp if used
|
||||
{
|
||||
table->timestamp_field->set_time();
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new
|
|||
!strcmp(((Item_field*)new_item)->table_name,iif->table_name) &&
|
||||
!strcmp(((Item_field*)new_item)->field_name,iif->field_name))
|
||||
{
|
||||
not_found=false;
|
||||
not_found= 0;
|
||||
((Item_field*)new_item)->db_name=iif->db_name;
|
||||
Item_field *new_one=new Item_field(iif->db_name, iif->table_name, iif->field_name);
|
||||
privlist.push_back(new_one);
|
||||
|
|
@ -151,7 +151,7 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
|
|||
if (cursor->do_redirect)
|
||||
{
|
||||
cursor->table= ((TABLE_LIST*) cursor->table)->table;
|
||||
cursor->do_redirect=false;
|
||||
cursor->do_redirect= 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,6 +193,8 @@ static bool check_user(THD *thd,enum_server_command command, const char *user,
|
|||
thd->db_length=0;
|
||||
USER_RESOURCES ur;
|
||||
|
||||
if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
|
||||
return 1;
|
||||
if (!(thd->user = my_strdup(user, MYF(0))))
|
||||
{
|
||||
send_error(thd,ER_OUT_OF_RESOURCES);
|
||||
|
|
@ -419,7 +421,7 @@ end:
|
|||
}
|
||||
|
||||
|
||||
static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them=false)
|
||||
static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
|
||||
{
|
||||
|
||||
(void) pthread_mutex_lock(&LOCK_user_conn);
|
||||
|
|
@ -593,8 +595,6 @@ check_connections(THD *thd)
|
|||
char *user= (char*) net->read_pos+5;
|
||||
char *passwd= strend(user)+1;
|
||||
char *db=0;
|
||||
if (passwd[0] && strlen(passwd) != SCRAMBLE_LENGTH)
|
||||
return ER_HANDSHAKE_ERROR;
|
||||
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
|
||||
db=strend(passwd)+1;
|
||||
if (thd->client_capabilities & CLIENT_INTERACTIVE)
|
||||
|
|
@ -1914,59 +1914,24 @@ mysql_execute_command(THD *thd)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
{
|
||||
multi_update *result;
|
||||
uint table_count;
|
||||
TABLE_LIST *auxi;
|
||||
const char *msg=0;
|
||||
|
||||
for (auxi= (TABLE_LIST*) tables, table_count=0 ; auxi ; auxi=auxi->next)
|
||||
table_count++;
|
||||
|
||||
const char *msg= 0;
|
||||
if (select_lex->order_list.elements)
|
||||
msg="ORDER BY";
|
||||
msg= "ORDER BY";
|
||||
else if (select_lex->select_limit && select_lex->select_limit !=
|
||||
HA_POS_ERROR)
|
||||
msg="LIMIT";
|
||||
msg= "LIMIT";
|
||||
if (msg)
|
||||
{
|
||||
net_printf(thd, ER_WRONG_USAGE, "UPDATE", msg);
|
||||
res= 1;
|
||||
break;
|
||||
}
|
||||
|
||||
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
|
||||
if ((res=open_and_lock_tables(thd,tables)))
|
||||
break;
|
||||
unit->select_limit_cnt= HA_POS_ERROR;
|
||||
if (!setup_fields(thd,tables,select_lex->item_list,1,0,0) &&
|
||||
!setup_fields(thd,tables,lex->value_list,0,0,0) &&
|
||||
!thd->fatal_error &&
|
||||
(result=new multi_update(thd,tables,select_lex->item_list,
|
||||
lex->duplicates, table_count)))
|
||||
{
|
||||
List <Item> total_list;
|
||||
List_iterator <Item> field_list(select_lex->item_list);
|
||||
List_iterator <Item> value_list(lex->value_list);
|
||||
Item *item;
|
||||
while ((item=field_list++))
|
||||
total_list.push_back(item);
|
||||
while ((item=value_list++))
|
||||
total_list.push_back(item);
|
||||
|
||||
res= mysql_select(thd, tables, total_list,
|
||||
res= mysql_multi_update(thd,tables,
|
||||
&select_lex->item_list,
|
||||
&lex->value_list,
|
||||
select_lex->where,
|
||||
(ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE,
|
||||
result, unit, select_lex, 0);
|
||||
delete result;
|
||||
if (thd->net.report_error)
|
||||
res= -1;
|
||||
}
|
||||
else
|
||||
res= -1; // Error is not sent
|
||||
close_thread_tables(thd);
|
||||
select_lex->options,
|
||||
lex->duplicates, unit, select_lex);
|
||||
}
|
||||
break;
|
||||
case SQLCOM_REPLACE:
|
||||
|
|
@ -3022,16 +2987,6 @@ mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
}
|
||||
|
||||
|
||||
inline static void
|
||||
link_in_list(SQL_LIST *list,byte *element,byte **next)
|
||||
{
|
||||
list->elements++;
|
||||
(*list->next)=element;
|
||||
list->next=next;
|
||||
*next=0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** Store field definition for create
|
||||
** Return 0 if ok
|
||||
|
|
@ -3344,7 +3299,7 @@ void store_position_for_column(const char *name)
|
|||
}
|
||||
|
||||
bool
|
||||
add_proc_to_list(Item *item)
|
||||
add_proc_to_list(THD* thd, Item *item)
|
||||
{
|
||||
ORDER *order;
|
||||
Item **item_ptr;
|
||||
|
|
@ -3355,7 +3310,7 @@ add_proc_to_list(Item *item)
|
|||
*item_ptr= item;
|
||||
order->item=item_ptr;
|
||||
order->free_me=0;
|
||||
link_in_list(¤t_lex->proc_list,(byte*) order,(byte**) &order->next);
|
||||
thd->lex.proc_list.link_in_list((byte*) order,(byte**) &order->next);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -3409,7 +3364,7 @@ bool add_to_list(SQL_LIST &list,Item *item,bool asc)
|
|||
order->asc = asc;
|
||||
order->free_me=0;
|
||||
order->used=0;
|
||||
link_in_list(&list,(byte*) order,(byte**) &order->next);
|
||||
list.link_in_list((byte*) order,(byte**) &order->next);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
|
@ -3500,7 +3455,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(Table_ident *table,
|
|||
}
|
||||
}
|
||||
}
|
||||
link_in_list(&table_list, (byte*) ptr, (byte**) &ptr->next);
|
||||
table_list.link_in_list((byte*) ptr, (byte**) &ptr->next);
|
||||
DBUG_RETURN(ptr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,9 @@ static void read_cached_record(JOIN_TAB *tab);
|
|||
static bool cmp_buffer_with_ref(JOIN_TAB *tab);
|
||||
static bool setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
List<Item> &all_fields,ORDER *new_order);
|
||||
static ORDER *create_distinct_group(ORDER *order, List<Item> &fields);
|
||||
static ORDER *create_distinct_group(THD *thd, ORDER *order,
|
||||
List<Item> &fields,
|
||||
bool *all_order_by_fields_used);
|
||||
static bool test_if_subpart(ORDER *a,ORDER *b);
|
||||
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
|
||||
static void calc_group_buffer(JOIN *join,ORDER *group);
|
||||
|
|
@ -343,6 +345,10 @@ JOIN::prepare(TABLE_LIST *tables_init,
|
|||
this->group= group_list != 0;
|
||||
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
|
||||
unit->select_limit_cnt);
|
||||
/* select_limit is used to decide if we are likely to scan the whole table */
|
||||
select_limit= unit->select_limit_cnt;
|
||||
if (having || (select_options & OPTION_FOUND_ROWS))
|
||||
select_limit= HA_POS_ERROR;
|
||||
do_send_rows = (unit->select_limit_cnt) ? 1 : 0;
|
||||
this->unit= unit;
|
||||
|
||||
|
|
@ -371,6 +377,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
|
|||
int
|
||||
JOIN::optimize()
|
||||
{
|
||||
ha_rows select_limit;
|
||||
DBUG_ENTER("JOIN::optimize");
|
||||
|
||||
#ifdef HAVE_REF_TO_FIELDS // Not done yet
|
||||
|
|
@ -403,7 +410,8 @@ JOIN::optimize()
|
|||
// normal error processing & cleanup
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
if (cond_value == Item::COND_FALSE || (!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
|
||||
if (cond_value == Item::COND_FALSE ||
|
||||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
|
||||
{ /* Impossible cond */
|
||||
zero_result_cause= "Impossible WHERE";
|
||||
DBUG_RETURN(0);
|
||||
|
|
@ -451,11 +459,12 @@ JOIN::optimize()
|
|||
found_const_table_map= 0;
|
||||
}
|
||||
thd->proc_info= "preparing";
|
||||
result->initialize_tables(this);
|
||||
if (result->initialize_tables(this))
|
||||
DBUG_RETURN(-1);
|
||||
if (const_table_map != found_const_table_map &&
|
||||
!(select_options & SELECT_DESCRIBE))
|
||||
{
|
||||
zero_result_cause= "";
|
||||
zero_result_cause= "no matching row in const table";
|
||||
select_options= 0; //TODO why option in return_zero_rows was droped
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
|
@ -513,21 +522,46 @@ JOIN::optimize()
|
|||
if (! hidden_group_fields)
|
||||
select_distinct=0;
|
||||
}
|
||||
else if (select_distinct && tables - const_tables == 1 &&
|
||||
(unit->select_limit_cnt == HA_POS_ERROR ||
|
||||
(select_options & OPTION_FOUND_ROWS) ||
|
||||
order &&
|
||||
!(skip_sort_order=
|
||||
test_if_skip_sort_order(&join_tab[const_tables],
|
||||
order,
|
||||
unit->select_limit_cnt,
|
||||
1))))
|
||||
else if (select_distinct && tables - const_tables == 1)
|
||||
{
|
||||
if ((group_list= create_distinct_group(order, fields_list)))
|
||||
/*
|
||||
We are only using one table. In this case we change DISTINCT to a
|
||||
GROUP BY query if:
|
||||
- The GROUP BY can be done through indexes (no sort) and the ORDER
|
||||
BY only uses selected fields.
|
||||
(In this case we can later optimize away GROUP BY and ORDER BY)
|
||||
- We are scanning the whole table without LIMIT
|
||||
This can happen if:
|
||||
- We are using CALC_FOUND_ROWS
|
||||
- We are using an ORDER BY that can't be optimized away.
|
||||
|
||||
We don't want to use this optimization when we are using LIMIT
|
||||
because in this case we can just create a temporary table that
|
||||
holds LIMIT rows and stop when this table is full.
|
||||
*/
|
||||
JOIN_TAB *tab= &join_tab[const_tables];
|
||||
bool all_order_fields_used;
|
||||
if (order)
|
||||
skip_sort_order= test_if_skip_sort_order(tab, order, select_limit, 1);
|
||||
if ((group=create_distinct_group(thd, order, fields_list,
|
||||
&all_order_fields_used)))
|
||||
{
|
||||
bool skip_group= (skip_sort_order &&
|
||||
test_if_skip_sort_order(tab, group, select_limit,
|
||||
1) != 0);
|
||||
if ((skip_group && all_order_fields_used) ||
|
||||
select_limit == HA_POS_ERROR ||
|
||||
(order && !skip_sort_order))
|
||||
{
|
||||
/* Change DISTINCT to GROUP BY */
|
||||
select_distinct= 0;
|
||||
no_order= !order;
|
||||
group= 1; // For end_write_group
|
||||
if (all_order_fields_used)
|
||||
order=0;
|
||||
group=1; // For end_write_group
|
||||
}
|
||||
else
|
||||
group= 0;
|
||||
}
|
||||
else if (thd->fatal_error) // End of memory
|
||||
DBUG_RETURN(-1);
|
||||
|
|
@ -727,11 +761,9 @@ JOIN::exec()
|
|||
order=group_list;
|
||||
if (order &&
|
||||
(const_tables == tables ||
|
||||
(simple_order &&
|
||||
((simple_order || skip_sort_order) &&
|
||||
test_if_skip_sort_order(&join_tab[const_tables], order,
|
||||
(select_options & OPTION_FOUND_ROWS) ?
|
||||
HA_POS_ERROR : unit->select_limit_cnt,
|
||||
0))))
|
||||
select_limit, 0))))
|
||||
order=0;
|
||||
select_describe(this, need_tmp,
|
||||
order != 0 && !skip_sort_order,
|
||||
|
|
@ -759,7 +791,7 @@ JOIN::exec()
|
|||
group_list ? 0 : select_distinct,
|
||||
group_list && simple_group,
|
||||
(order == 0 || skip_sort_order) &&
|
||||
!(select_options & OPTION_FOUND_ROWS),
|
||||
select_limit != HA_POS_ERROR,
|
||||
select_options, unit)))
|
||||
DBUG_VOID_RETURN;
|
||||
|
||||
|
|
@ -813,8 +845,9 @@ JOIN::exec()
|
|||
/* Optimize "select distinct b from t1 order by key_part_1 limit #" */
|
||||
if (order && skip_sort_order)
|
||||
{
|
||||
(void) test_if_skip_sort_order(&this->join_tab[const_tables],
|
||||
order, unit->select_limit_cnt, 0);
|
||||
/* Should always succeed */
|
||||
if (test_if_skip_sort_order(&this->join_tab[const_tables],
|
||||
order, unit->select_limit_cnt, 0))
|
||||
order=0;
|
||||
}
|
||||
}
|
||||
|
|
@ -989,8 +1022,7 @@ JOIN::exec()
|
|||
}
|
||||
}
|
||||
{
|
||||
ha_rows select_limit= unit->select_limit_cnt;
|
||||
if (having || group || (select_options & OPTION_FOUND_ROWS))
|
||||
if (group)
|
||||
select_limit= HA_POS_ERROR;
|
||||
else
|
||||
{
|
||||
|
|
@ -1002,7 +1034,13 @@ JOIN::exec()
|
|||
JOIN_TAB *end_table= &join_tab[tables];
|
||||
for (; table < end_table ; table++)
|
||||
{
|
||||
if (table->select_cond)
|
||||
/*
|
||||
table->keyuse is set in the case there was an original WHERE clause
|
||||
on the table that was optimized away.
|
||||
table->on_expr tells us that it was a LEFT JOIN and there will be
|
||||
at least one row generated from the table.
|
||||
*/
|
||||
if (table->select_cond || (table->keyuse && !table->on_expr))
|
||||
{
|
||||
/* We have to sort all rows */
|
||||
select_limit= HA_POS_ERROR;
|
||||
|
|
@ -1186,13 +1224,21 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Calculate the best possible join and initialize the join structure
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 Fatal error
|
||||
*/
|
||||
|
||||
static bool
|
||||
make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
||||
DYNAMIC_ARRAY *keyuse_array)
|
||||
{
|
||||
int error;
|
||||
uint i,table_count,const_count,found_ref,refs,key,const_ref,eq_part;
|
||||
table_map const_table_map,found_const_table_map,all_table_map;
|
||||
table_map found_const_table_map,all_table_map;
|
||||
TABLE **table_vector;
|
||||
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
|
||||
SQL_SELECT *select;
|
||||
|
|
@ -1212,7 +1258,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||
join->best_ref=stat_vector;
|
||||
|
||||
stat_end=stat+table_count;
|
||||
const_table_map=found_const_table_map=all_table_map=0;
|
||||
found_const_table_map=all_table_map=0;
|
||||
const_count=0;
|
||||
|
||||
for (s=stat,i=0 ; tables ; s++,tables=tables->next,i++)
|
||||
|
|
@ -1303,7 +1349,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||
DBUG_RETURN(1);
|
||||
|
||||
/* Read tables with 0 or 1 rows (system tables) */
|
||||
join->const_table_map=const_table_map;
|
||||
join->const_table_map= 0;
|
||||
|
||||
for (POSITION *p_pos=join->positions, *p_end=p_pos+const_count;
|
||||
p_pos < p_end ;
|
||||
|
|
@ -1340,16 +1386,16 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||
if (s->dependent) // If dependent on some table
|
||||
{
|
||||
// All dep. must be constants
|
||||
if (s->dependent & ~(join->const_table_map))
|
||||
if (s->dependent & ~(found_const_table_map))
|
||||
continue;
|
||||
if (table->file->records <= 1L &&
|
||||
!(table->file->table_flags() & HA_NOT_EXACT_COUNT))
|
||||
{ // system table
|
||||
int tmp;
|
||||
int tmp= 0;
|
||||
s->type=JT_SYSTEM;
|
||||
join->const_table_map|=table->map;
|
||||
set_position(join,const_count++,s,(KEYUSE*) 0);
|
||||
if ((tmp=join_read_const_table(s,join->positions+const_count-1)))
|
||||
if ((tmp= join_read_const_table(s,join->positions+const_count-1)))
|
||||
{
|
||||
if (tmp > 0)
|
||||
DBUG_RETURN(1); // Fatal error
|
||||
|
|
@ -1374,7 +1420,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||
{
|
||||
if (keyuse->val->type() != Item::NULL_ITEM)
|
||||
{
|
||||
if (!((~join->const_table_map) & keyuse->used_tables))
|
||||
if (!((~found_const_table_map) & keyuse->used_tables))
|
||||
const_ref|= (key_map) 1 << keyuse->keypart;
|
||||
else
|
||||
refs|=keyuse->used_tables;
|
||||
|
|
@ -1395,7 +1441,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||
join->const_table_map|=table->map;
|
||||
set_position(join,const_count++,s,start_keyuse);
|
||||
if (create_ref_for_key(join, s, start_keyuse,
|
||||
join->const_table_map))
|
||||
found_const_table_map))
|
||||
DBUG_RETURN(1);
|
||||
if ((tmp=join_read_const_table(s,
|
||||
join->positions+const_count-1)))
|
||||
|
|
@ -1443,8 +1489,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
|
|||
{
|
||||
ha_rows records;
|
||||
if (!select)
|
||||
select=make_select(s->table, join->const_table_map,
|
||||
join->const_table_map,
|
||||
select=make_select(s->table, found_const_table_map,
|
||||
found_const_table_map,
|
||||
and_conds(conds,s->on_expr),&error);
|
||||
records=get_quick_record_count(select,s->table, s->const_keys,
|
||||
join->row_limit);
|
||||
|
|
@ -2607,12 +2653,13 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
|
|||
bool
|
||||
store_val_in_field(Field *field,Item *item)
|
||||
{
|
||||
bool error;
|
||||
THD *thd=current_thd;
|
||||
ha_rows cuted_fields=thd->cuted_fields;
|
||||
thd->count_cuted_fields=1;
|
||||
(void) item->save_in_field(field);
|
||||
error= item->save_in_field(field, 1);
|
||||
thd->count_cuted_fields=0;
|
||||
return cuted_fields != thd->cuted_fields;
|
||||
return error || cuted_fields != thd->cuted_fields;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2957,6 +3004,38 @@ make_join_readinfo(JOIN *join, uint options)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Give error if we some tables are done with a full join
|
||||
|
||||
SYNOPSIS
|
||||
error_if_full_join()
|
||||
join Join condition
|
||||
|
||||
USAGE
|
||||
This is used by multi_table_update and multi_table_delete when running
|
||||
in safe mode
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 Error (full join used)
|
||||
*/
|
||||
|
||||
bool error_if_full_join(JOIN *join)
|
||||
{
|
||||
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
|
||||
tab < end;
|
||||
tab++)
|
||||
{
|
||||
if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
|
||||
{
|
||||
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
join_free(JOIN *join)
|
||||
{
|
||||
|
|
@ -3021,9 +3100,7 @@ join_free(JOIN *join)
|
|||
}
|
||||
join->group_fields.delete_elements();
|
||||
join->tmp_table_param.copy_funcs.delete_elements();
|
||||
if (join->tmp_table_param.copy_field) // Because of bug in ecc
|
||||
delete [] join->tmp_table_param.copy_field;
|
||||
join->tmp_table_param.copy_field=0;
|
||||
join->tmp_table_param.cleanup();
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
@ -3655,12 +3732,34 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
|
|||
|
||||
|
||||
/****************************************************************************
|
||||
Create a temp table according to a field list.
|
||||
Set distinct if duplicates could be removed
|
||||
Given fields field pointers are changed to point at tmp_table
|
||||
for send_fields
|
||||
Create internal temporary table
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
Create field for temporary table
|
||||
|
||||
SYNOPSIS
|
||||
create_tmp_field()
|
||||
thd Thread handler
|
||||
table Temporary table
|
||||
item Item to create a field for
|
||||
type Type of item (normally item->type)
|
||||
copy_func If set and item is a function, store copy of item
|
||||
in this array
|
||||
group 1 if we are going to do a relative group by on result
|
||||
modify_item 1 if item->result_field should point to new item.
|
||||
This is relevent for how fill_record() is going to
|
||||
work:
|
||||
If modify_item is 1 then fill_record() will update
|
||||
the record in the original table.
|
||||
If modify_item is 0 then fill_record() will update
|
||||
the temporary table
|
||||
|
||||
RETURN
|
||||
0 on error
|
||||
new_created field
|
||||
*/
|
||||
|
||||
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
Item_result_field ***copy_func, Field **from_field,
|
||||
bool group, bool modify_item)
|
||||
|
|
@ -3778,6 +3877,13 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Create a temp table according to a field list.
|
||||
Set distinct if duplicates could be removed
|
||||
Given fields field pointers are changed to point at tmp_table
|
||||
for send_fields
|
||||
*/
|
||||
|
||||
TABLE *
|
||||
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
||||
ORDER *group, bool distinct, bool save_sum_fields,
|
||||
|
|
@ -3940,9 +4046,19 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
The last parameter to create_tmp_field() is a bit tricky:
|
||||
|
||||
We need to set it to 0 in union, to get fill_record() to modify the
|
||||
temporary table.
|
||||
We need to set it to 1 on multi-table-update and in select to
|
||||
write rows to the temporary table.
|
||||
We here distinguish between UNION and multi-table-updates by the fact
|
||||
that in the later case group is set to the row pointer.
|
||||
*/
|
||||
Field *new_field=create_tmp_field(thd, table, item,type, ©_func,
|
||||
tmp_from_field, group != 0,
|
||||
not_all_columns);
|
||||
not_all_columns || group !=0);
|
||||
if (!new_field)
|
||||
{
|
||||
if (thd->fatal_error)
|
||||
|
|
@ -4258,7 +4374,6 @@ static bool open_tmp_table(TABLE *table)
|
|||
table->db_stat=0;
|
||||
return(1);
|
||||
}
|
||||
/* VOID(ha_lock(table,F_WRLCK)); */ /* Single thread table */
|
||||
(void) table->file->extra(HA_EXTRA_QUICK); /* Faster */
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -4411,12 +4526,11 @@ free_tmp_table(THD *thd, TABLE *entry)
|
|||
* If a HEAP table gets full, create a MyISAM table and copy all rows to this
|
||||
*/
|
||||
|
||||
bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
|
||||
bool ignore_last_dupp_key_error)
|
||||
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
|
||||
int error, bool ignore_last_dupp_key_error)
|
||||
{
|
||||
TABLE new_table;
|
||||
const char *save_proc_info;
|
||||
THD *thd=current_thd;
|
||||
int write_err;
|
||||
DBUG_ENTER("create_myisam_from_heap");
|
||||
|
||||
|
|
@ -5392,7 +5506,8 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
|||
if (error == HA_ERR_FOUND_DUPP_KEY ||
|
||||
error == HA_ERR_FOUND_DUPP_UNIQUE)
|
||||
goto end;
|
||||
if (create_myisam_from_heap(table, &join->tmp_table_param, error,1))
|
||||
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
|
||||
error,1))
|
||||
DBUG_RETURN(-1); // Not a table_is_full error
|
||||
table->uniques=0; // To ensure rows are the same
|
||||
}
|
||||
|
|
@ -5469,7 +5584,8 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
|||
copy_funcs(join->tmp_table_param.funcs);
|
||||
if ((error=table->file->write_row(table->record[0])))
|
||||
{
|
||||
if (create_myisam_from_heap(table, &join->tmp_table_param, error, 0))
|
||||
if (create_myisam_from_heap(join->thd, table, &join->tmp_table_param,
|
||||
error, 0))
|
||||
DBUG_RETURN(-1); // Not a table_is_full error
|
||||
/* Change method to update rows */
|
||||
table->file->index_init(0);
|
||||
|
|
@ -5563,7 +5679,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
|
|||
{
|
||||
if ((error=table->file->write_row(table->record[0])))
|
||||
{
|
||||
if (create_myisam_from_heap(table, &join->tmp_table_param,
|
||||
if (create_myisam_from_heap(join.thd, table,
|
||||
&join->tmp_table_param,
|
||||
error, 0))
|
||||
DBUG_RETURN(-1); // Not a table_is_full error
|
||||
}
|
||||
|
|
@ -6769,12 +6886,14 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
|||
*/
|
||||
|
||||
static ORDER *
|
||||
create_distinct_group(ORDER *order_list,List<Item> &fields)
|
||||
create_distinct_group(THD *thd, ORDER *order_list, List<Item> &fields,
|
||||
bool *all_order_by_fields_used)
|
||||
{
|
||||
List_iterator<Item> li(fields);
|
||||
Item *item;
|
||||
ORDER *order,*group,**prev;
|
||||
|
||||
*all_order_by_fields_used= 1;
|
||||
while ((item=li++))
|
||||
item->marker=0; /* Marker that field is not used */
|
||||
|
||||
|
|
@ -6783,13 +6902,15 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
|
|||
{
|
||||
if (order->in_field_list)
|
||||
{
|
||||
ORDER *ord=(ORDER*) sql_memdup(order,sizeof(ORDER));
|
||||
ORDER *ord=(ORDER*) thd->memdup((char*) order,sizeof(ORDER));
|
||||
if (!ord)
|
||||
return 0;
|
||||
*prev=ord;
|
||||
prev= &ord->next;
|
||||
(*ord->item)->marker=1;
|
||||
}
|
||||
else
|
||||
*all_order_by_fields_used= 0;
|
||||
}
|
||||
|
||||
li.rewind();
|
||||
|
|
@ -6799,7 +6920,7 @@ create_distinct_group(ORDER *order_list,List<Item> &fields)
|
|||
continue;
|
||||
if (!item->marker)
|
||||
{
|
||||
ORDER *ord=(ORDER*) sql_calloc(sizeof(ORDER));
|
||||
ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
|
||||
if (!ord)
|
||||
return 0;
|
||||
ord->item=li.ref();
|
||||
|
|
@ -7251,7 +7372,7 @@ copy_sum_funcs(Item_sum **func_ptr)
|
|||
{
|
||||
Item_sum *func;
|
||||
for (; (func = *func_ptr) ; func_ptr++)
|
||||
(void) func->save_in_field(func->result_field);
|
||||
(void) func->save_in_field(func->result_field, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -7282,7 +7403,7 @@ copy_funcs(Item_result_field **func_ptr)
|
|||
{
|
||||
Item_result_field *func;
|
||||
for (; (func = *func_ptr) ; func_ptr++)
|
||||
(void) func->save_in_field(func->result_field);
|
||||
(void) func->save_in_field(func->result_field, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,8 @@ typedef struct st_position { /* Used in find_best */
|
|||
|
||||
/* Param to create temporary tables when doing SELECT:s */
|
||||
|
||||
class TMP_TABLE_PARAM {
|
||||
class TMP_TABLE_PARAM :public Sql_alloc
|
||||
{
|
||||
public:
|
||||
List<Item> copy_funcs;
|
||||
List_iterator_fast<Item> copy_funcs_it;
|
||||
|
|
@ -343,8 +344,7 @@ public:
|
|||
{}
|
||||
bool copy()
|
||||
{
|
||||
(void) item->save_in_field(to_field);
|
||||
return err != 0;
|
||||
return item->save_in_field(to_field, 1) || err != 0;
|
||||
}
|
||||
const char *name() const { return "func"; }
|
||||
};
|
||||
|
|
@ -367,7 +367,8 @@ public:
|
|||
if (!inited)
|
||||
{
|
||||
inited=1;
|
||||
(void)item->save_in_field(to_field);
|
||||
if (item->save_in_field(to_field, 1))
|
||||
err= 1;
|
||||
}
|
||||
return err != 0;
|
||||
}
|
||||
|
|
@ -375,3 +376,4 @@ public:
|
|||
};
|
||||
|
||||
bool cp_buffer_from_ref(TABLE_REF *ref);
|
||||
bool error_if_full_join(JOIN *join);
|
||||
|
|
|
|||
|
|
@ -1885,8 +1885,14 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
/* We changed a temporary table */
|
||||
if (error)
|
||||
{
|
||||
/*
|
||||
* The following function call will also free a
|
||||
* new_table pointer.
|
||||
* Therefore, here new_table pointer is not free'd as it is
|
||||
* free'd in close_temporary() which is called by by the
|
||||
* close_temporary_table() function.
|
||||
*/
|
||||
close_temporary_table(thd,new_db,tmp_name);
|
||||
my_free((gptr) new_table,MYF(0));
|
||||
goto err;
|
||||
}
|
||||
/* Close lock if this is a transactional table */
|
||||
|
|
@ -2206,7 +2212,6 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||
if (to->file->external_lock(thd,F_UNLCK))
|
||||
error=1;
|
||||
err:
|
||||
tmp_error = ha_recovery_logging(thd,TRUE);
|
||||
free_io_cache(from);
|
||||
*copied= found_count;
|
||||
*deleted=delete_count;
|
||||
|
|
|
|||
|
|
@ -203,6 +203,8 @@ void udf_init()
|
|||
new_thd->version--; // Force close to free memory
|
||||
close_thread_tables(new_thd);
|
||||
delete new_thd;
|
||||
/* Remember that we don't have a THD */
|
||||
my_pthread_setspecific_ptr(THR_THD, 0);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ int mysql_union(THD *thd, LEX *lex, select_result *result)
|
|||
***************************************************************************/
|
||||
|
||||
select_union::select_union(TABLE *table_par)
|
||||
:table(table_par)
|
||||
:table(table_par), not_describe(0)
|
||||
{
|
||||
bzero((char*) &info,sizeof(info));
|
||||
/*
|
||||
|
|
@ -59,7 +59,7 @@ select_union::~select_union()
|
|||
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
unit= u;
|
||||
if (save_time_stamp && list.elements != table->fields)
|
||||
if (not_describe && list.elements != table->fields)
|
||||
{
|
||||
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
|
||||
ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
|
||||
|
|
@ -117,7 +117,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
|
|||
prepared= 1;
|
||||
union_result=0;
|
||||
res= 0;
|
||||
found_rows_for_union= false;
|
||||
found_rows_for_union= 0;
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
this->thd= thd;
|
||||
this->result= result;
|
||||
|
|
@ -165,7 +165,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
|
|||
if (!(union_result=new select_union(table)))
|
||||
goto err;
|
||||
|
||||
union_result->save_time_stamp=1;
|
||||
union_result->not_describe=1;
|
||||
union_result->tmp_table_param=&tmp_table_param;
|
||||
|
||||
// prepare selects
|
||||
|
|
|
|||
|
|
@ -29,10 +29,12 @@ static bool compare_record(TABLE *table, ulong query_id)
|
|||
{
|
||||
if (!table->blob_fields)
|
||||
return cmp_record(table,1);
|
||||
/* Compare null bits */
|
||||
if (memcmp(table->null_flags,
|
||||
table->null_flags+table->rec_buff_length,
|
||||
table->null_bytes))
|
||||
return 1; // Diff in NULL value
|
||||
/* Compare updated fields */
|
||||
for (Field **ptr=table->field ; *ptr ; ptr++)
|
||||
{
|
||||
if ((*ptr)->query_id == query_id &&
|
||||
|
|
@ -56,7 +58,7 @@ int mysql_update(THD *thd,
|
|||
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
|
||||
bool used_key_is_modified, transactional_table, log_delayed;
|
||||
int error=0;
|
||||
uint save_time_stamp, used_index, want_privilege;
|
||||
uint used_index, want_privilege;
|
||||
ulong query_id=thd->query_id, timestamp_query_id;
|
||||
key_map old_used_keys;
|
||||
TABLE *table;
|
||||
|
|
@ -73,7 +75,6 @@ int mysql_update(THD *thd,
|
|||
fix_tables_pointers(thd->lex.all_selects_list);
|
||||
table= table_list->table;
|
||||
|
||||
save_time_stamp=table->time_stamp;
|
||||
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||
thd->proc_info="init";
|
||||
|
||||
|
|
@ -103,6 +104,7 @@ int mysql_update(THD *thd,
|
|||
{
|
||||
timestamp_query_id=table->timestamp_field->query_id;
|
||||
table->timestamp_field->query_id=thd->query_id-1;
|
||||
table->time_stamp= table->timestamp_field->offset() +1;
|
||||
}
|
||||
|
||||
/* Check the fields we are going to modify */
|
||||
|
|
@ -122,7 +124,6 @@ int mysql_update(THD *thd,
|
|||
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
|
||||
if (setup_fields(thd,update_table_list,values,0,0,0))
|
||||
{
|
||||
table->time_stamp=save_time_stamp; // Restore timestamp pointer
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +134,6 @@ int mysql_update(THD *thd,
|
|||
(select && select->check_quick(safe_update, limit)) || !limit)
|
||||
{
|
||||
delete select;
|
||||
table->time_stamp=save_time_stamp; // Restore timestamp pointer
|
||||
if (error)
|
||||
{
|
||||
DBUG_RETURN(-1); // Error in where
|
||||
|
|
@ -148,7 +148,6 @@ int mysql_update(THD *thd,
|
|||
if (safe_update && !using_limit)
|
||||
{
|
||||
delete select;
|
||||
table->time_stamp=save_time_stamp;
|
||||
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
|
@ -167,8 +166,8 @@ int mysql_update(THD *thd,
|
|||
if (used_key_is_modified || order)
|
||||
{
|
||||
/*
|
||||
** We can't update table directly; We must first search after all
|
||||
** matching rows before updating the table!
|
||||
We can't update table directly; We must first search after all
|
||||
matching rows before updating the table!
|
||||
*/
|
||||
table->file->extra(HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE);
|
||||
IO_CACHE tempfile;
|
||||
|
|
@ -176,7 +175,6 @@ int mysql_update(THD *thd,
|
|||
DISK_BUFFER_SIZE, MYF(MY_WME)))
|
||||
{
|
||||
delete select; /* purecov: inspected */
|
||||
table->time_stamp=save_time_stamp; // Restore timestamp pointer /* purecov: inspected */
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
if (old_used_keys & ((key_map) 1 << used_index))
|
||||
|
|
@ -207,7 +205,6 @@ int mysql_update(THD *thd,
|
|||
== HA_POS_ERROR)
|
||||
{
|
||||
delete select;
|
||||
table->time_stamp=save_time_stamp; // Restore timestamp pointer
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
|
@ -261,7 +258,6 @@ int mysql_update(THD *thd,
|
|||
if (error >= 0)
|
||||
{
|
||||
delete select;
|
||||
table->time_stamp=save_time_stamp; // Restore timestamp pointer
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
|
@ -311,7 +307,6 @@ int mysql_update(THD *thd,
|
|||
end_read_record(&info);
|
||||
thd->proc_info="end";
|
||||
VOID(table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY));
|
||||
table->time_stamp=save_time_stamp; // Restore auto timestamp pointer
|
||||
transactional_table= table->file->has_transactions();
|
||||
log_delayed= (transactional_table || table->tmp_table);
|
||||
if (updated && (error <= 0 || !transactional_table))
|
||||
|
|
@ -365,331 +360,344 @@ int mysql_update(THD *thd,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
Update multiple tables from join
|
||||
***************************************************************************/
|
||||
|
||||
multi_update::multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> &fs,
|
||||
/*
|
||||
Setup multi-update handling and call SELECT to do the join
|
||||
*/
|
||||
|
||||
int mysql_multi_update(THD *thd,
|
||||
TABLE_LIST *table_list,
|
||||
List<Item> *fields,
|
||||
List<Item> *values,
|
||||
COND *conds,
|
||||
ulong options,
|
||||
enum enum_duplicates handle_duplicates,
|
||||
uint num)
|
||||
: update_tables (ut), thd(thd_arg), updated(0), found(0), fields(fs),
|
||||
dupl(handle_duplicates), num_of_tables(num), num_fields(0), num_updated(0),
|
||||
error(0), do_update(false)
|
||||
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
|
||||
{
|
||||
save_time_stamps = (uint *) sql_calloc (sizeof(uint) * num_of_tables);
|
||||
tmp_tables = (TABLE **)NULL;
|
||||
int counter=0;
|
||||
ulong timestamp_query_id;
|
||||
not_trans_safe=false;
|
||||
for (TABLE_LIST *dt=ut ; dt ; dt=dt->next,counter++)
|
||||
int res;
|
||||
multi_update *result;
|
||||
TABLE_LIST *tl;
|
||||
DBUG_ENTER("mysql_multi_update");
|
||||
|
||||
table_list->grant.want_privilege=(SELECT_ACL & ~table_list->grant.privilege);
|
||||
if ((res=open_and_lock_tables(thd,table_list)))
|
||||
DBUG_RETURN(res);
|
||||
|
||||
thd->select_limit=HA_POS_ERROR;
|
||||
if (setup_fields(thd, table_list, *fields, 1, 0, 0))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
/*
|
||||
Count tables and setup timestamp handling
|
||||
*/
|
||||
for (tl= (TABLE_LIST*) table_list ; tl ; tl=tl->next)
|
||||
{
|
||||
TABLE *table=ut->table;
|
||||
// (void) ut->table->file->extra(HA_EXTRA_NO_KEYREAD);
|
||||
dt->table->used_keys=0;
|
||||
TABLE *table= tl->table;
|
||||
if (table->timestamp_field)
|
||||
{
|
||||
// Don't set timestamp column if this is modified
|
||||
timestamp_query_id=table->timestamp_field->query_id;
|
||||
table->timestamp_field->query_id=thd->query_id-1;
|
||||
if (table->timestamp_field->query_id == thd->query_id)
|
||||
table->time_stamp=0;
|
||||
else
|
||||
table->timestamp_field->query_id=timestamp_query_id;
|
||||
// Only set timestamp column if this is not modified
|
||||
if (table->timestamp_field->query_id != thd->query_id)
|
||||
table->time_stamp= table->timestamp_field->offset() +1;
|
||||
}
|
||||
save_time_stamps[counter]=table->time_stamp;
|
||||
}
|
||||
error = 1; // In case we do not reach prepare we have to reset timestamps
|
||||
|
||||
if (!(result=new multi_update(thd, table_list, fields, values,
|
||||
handle_duplicates)))
|
||||
DBUG_RETURN(-1);
|
||||
|
||||
List<Item> total_list;
|
||||
res= mysql_select(thd,table_list,total_list,
|
||||
conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
|
||||
(ORDER *)NULL,
|
||||
options | SELECT_NO_JOIN_CACHE,
|
||||
result, unit, select_lex, 0);
|
||||
|
||||
end:
|
||||
delete result;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
int
|
||||
multi_update::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
|
||||
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
|
||||
List<Item> *field_list, List<Item> *value_list,
|
||||
enum enum_duplicates handle_duplicates_arg)
|
||||
:all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0),
|
||||
updated(0), found(0), fields(field_list), values(value_list),
|
||||
table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg),
|
||||
do_update(1), trans_safe(0)
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
Connect fields with tables and create list of tables that are updated
|
||||
*/
|
||||
|
||||
int multi_update::prepare(List<Item> ¬_used_values)
|
||||
{
|
||||
TABLE_LIST *table_ref;
|
||||
SQL_LIST update;
|
||||
table_map tables_to_update= 0;
|
||||
Item_field *item;
|
||||
List_iterator_fast<Item> field_it(*fields);
|
||||
List_iterator_fast<Item> value_it(*values);
|
||||
uint i, max_fields;
|
||||
DBUG_ENTER("multi_update::prepare");
|
||||
unit= u;
|
||||
do_update = true;
|
||||
|
||||
thd->count_cuted_fields=1;
|
||||
thd->cuted_fields=0L;
|
||||
thd->proc_info="updating the main table";
|
||||
TABLE_LIST *table_ref;
|
||||
thd->proc_info="updating main table";
|
||||
|
||||
if (thd->options & OPTION_SAFE_UPDATES)
|
||||
while ((item= (Item_field *) field_it++))
|
||||
tables_to_update|= item->used_tables();
|
||||
|
||||
if (!tables_to_update)
|
||||
{
|
||||
for (table_ref=update_tables; table_ref; table_ref=table_ref->next)
|
||||
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
|
||||
"You didn't specify any tables to UPDATE");
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
We have to check values after setup_tables to get used_keys right in
|
||||
reference tables
|
||||
*/
|
||||
|
||||
if (setup_fields(thd, all_tables, *values, 1,0,0))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/*
|
||||
Save tables beeing updated in update_tables
|
||||
update_table->shared is position for table
|
||||
Don't use key read on tables that are updated
|
||||
*/
|
||||
|
||||
update.empty();
|
||||
for (table_ref= all_tables; table_ref; table_ref=table_ref->next)
|
||||
{
|
||||
TABLE *table=table_ref->table;
|
||||
if ((thd->options & OPTION_SAFE_UPDATES) && !table->quick_keys)
|
||||
if (tables_to_update & table->map)
|
||||
{
|
||||
my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
|
||||
TABLE_LIST *tl= (TABLE_LIST*) thd->memdup((char*) table_ref,
|
||||
sizeof(*tl));
|
||||
if (!tl)
|
||||
DBUG_RETURN(1);
|
||||
update.link_in_list((byte*) tl, (byte**) &tl->next);
|
||||
tl->shared= table_count++;
|
||||
table->no_keyread=1;
|
||||
table->used_keys=0;
|
||||
table->pos_in_table_list= tl;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Here I have to connect fields with tables and only update tables that
|
||||
need to be updated.
|
||||
I calculate num_updated and fill-up table_sequence
|
||||
Set table_list->shared to true or false, depending on whether table is
|
||||
to be updated or not
|
||||
*/
|
||||
table_count= update.elements;
|
||||
update_tables= (TABLE_LIST*) update.first;
|
||||
|
||||
Item_field *item;
|
||||
List_iterator<Item> it(fields);
|
||||
num_fields=fields.elements;
|
||||
field_sequence = (uint *) sql_alloc(sizeof(uint)*num_fields);
|
||||
uint *int_ptr=field_sequence;
|
||||
while ((item= (Item_field *)it++))
|
||||
{
|
||||
unsigned int counter=0;
|
||||
for (table_ref=update_tables; table_ref;
|
||||
table_ref=table_ref->next, counter++)
|
||||
{
|
||||
if (table_ref->table == item->field->table)
|
||||
{
|
||||
if (!table_ref->shared)
|
||||
{
|
||||
TABLE *tbl=table_ref->table;
|
||||
num_updated++;
|
||||
table_ref->shared=1;
|
||||
if (!not_trans_safe && !table_ref->table->file->has_transactions())
|
||||
not_trans_safe=true;
|
||||
// to be moved if initialize_tables has to be used
|
||||
tbl->no_keyread=1;
|
||||
tbl->used_keys=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!table_ref)
|
||||
{
|
||||
net_printf(thd, ER_NOT_SUPPORTED_YET, "JOIN SYNTAX WITH MULTI-TABLE UPDATES");
|
||||
tmp_tables = (TABLE **) thd->calloc(sizeof(TABLE *) * table_count);
|
||||
tmp_table_param = (TMP_TABLE_PARAM*) thd->calloc(sizeof(TMP_TABLE_PARAM) *
|
||||
table_count);
|
||||
fields_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
|
||||
table_count);
|
||||
values_for_table= (List_item **) thd->alloc(sizeof(List_item *) *
|
||||
table_count);
|
||||
if (thd->fatal_error)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
else
|
||||
*int_ptr++=counter;
|
||||
}
|
||||
if (!num_updated--)
|
||||
for (i=0 ; i < table_count ; i++)
|
||||
{
|
||||
net_printf(thd, ER_NOT_SUPPORTED_YET, "SET CLAUSE MUST CONTAIN TABLE.FIELD REFERENCE");
|
||||
DBUG_RETURN(1);
|
||||
fields_for_table[i]= new List_item;
|
||||
values_for_table[i]= new List_item;
|
||||
}
|
||||
if (thd->fatal_error)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/*
|
||||
Here, I have to allocate the array of temporary tables
|
||||
I have to treat a case of num_updated=1 differently in send_data() method.
|
||||
*/
|
||||
if (num_updated)
|
||||
{
|
||||
tmp_tables = (TABLE **) sql_calloc(sizeof(TABLE *) * num_updated);
|
||||
infos = (COPY_INFO *) sql_calloc(sizeof(COPY_INFO) * num_updated);
|
||||
fields_by_tables = (List_item **)sql_calloc(sizeof(List_item *) * (num_updated + 1));
|
||||
unsigned int counter;
|
||||
List<Item> *temp_fields;
|
||||
for (table_ref=update_tables, counter = 0; table_ref; table_ref=table_ref->next)
|
||||
{
|
||||
if (!table_ref->shared)
|
||||
continue;
|
||||
// Here we have to add row offset as an additional field ...
|
||||
if (!(temp_fields = (List_item *)sql_calloc(sizeof(List_item))))
|
||||
{
|
||||
error = 1; // A proper error message is due here
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
temp_fields->empty();
|
||||
it.rewind(); int_ptr=field_sequence;
|
||||
while ((item= (Item_field *)it++))
|
||||
{
|
||||
if (*int_ptr++ == counter)
|
||||
temp_fields->push_back(item);
|
||||
}
|
||||
if (counter)
|
||||
{
|
||||
Field_string offset(table_ref->table->file->ref_length, false,
|
||||
"offset", table_ref->table, my_charset_bin);
|
||||
temp_fields->push_front(new Item_field(((Field *)&offset)));
|
||||
/* Split fields into fields_for_table[] and values_by_table[] */
|
||||
|
||||
// Make a temporary table
|
||||
int cnt=counter-1;
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
|
||||
tmp_table_param.field_count=temp_fields->elements;
|
||||
if (!(tmp_tables[cnt]=create_tmp_table(thd, &tmp_table_param,
|
||||
*temp_fields,
|
||||
(ORDER*) 0, 1, 0, 0,
|
||||
TMP_TABLE_ALL_COLUMNS,
|
||||
unit)))
|
||||
field_it.rewind();
|
||||
while ((item= (Item_field *) field_it++))
|
||||
{
|
||||
error = 1; // A proper error message is due here
|
||||
Item *value= value_it++;
|
||||
uint offset= item->field->table->pos_in_table_list->shared;
|
||||
fields_for_table[offset]->push_back(item);
|
||||
values_for_table[offset]->push_back(value);
|
||||
}
|
||||
if (thd->fatal_error)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
tmp_tables[cnt]->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
infos[cnt].handle_duplicates=DUP_IGNORE;
|
||||
temp_fields->pop(); // because we shall use those for values only ...
|
||||
}
|
||||
fields_by_tables[counter]=temp_fields;
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
init_ftfuncs(thd, thd->lex.current_select->select_lex(), 1);
|
||||
error = 0; // Timestamps do not need to be restored, so far ...
|
||||
DBUG_RETURN(0);
|
||||
|
||||
/* Allocate copy fields */
|
||||
max_fields=0;
|
||||
for (i=0 ; i < table_count ; i++)
|
||||
set_if_bigger(max_fields, fields_for_table[i]->elements);
|
||||
copy_field= new Copy_field[max_fields];
|
||||
init_ftfuncs(thd,1);
|
||||
DBUG_RETURN(thd->fatal_error != 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
/*
|
||||
Store first used table in main_table as this should be updated first
|
||||
This is because we know that no row in this table will be read twice.
|
||||
|
||||
Create temporary tables to store changed values for all other tables
|
||||
that are updated.
|
||||
*/
|
||||
|
||||
bool
|
||||
multi_update::initialize_tables(JOIN *join)
|
||||
{
|
||||
#ifdef NOT_YET
|
||||
We skip it as it only makes a mess ...........
|
||||
TABLE_LIST *walk;
|
||||
table_map tables_to_update_from=0;
|
||||
for (walk= update_tables ; walk ; walk=walk->next)
|
||||
tables_to_update_from|= walk->table->map;
|
||||
TABLE_LIST *table_ref;
|
||||
DBUG_ENTER("initialize_tables");
|
||||
|
||||
walk= update_tables;
|
||||
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
|
||||
tab < end;
|
||||
tab++)
|
||||
if ((thd->options & OPTION_SAFE_UPDATES) && error_if_full_join(join))
|
||||
DBUG_RETURN(1);
|
||||
main_table=join->join_tab->table;
|
||||
trans_safe= transactional_tables= main_table->file->has_transactions();
|
||||
log_delayed= trans_safe || main_table->tmp_table != NO_TMP_TABLE;
|
||||
|
||||
/* Create a temporary table for all tables after except main table */
|
||||
for (table_ref= update_tables; table_ref; table_ref=table_ref->next)
|
||||
{
|
||||
if (tab->table->map & tables_to_update_from)
|
||||
TABLE *table=table_ref->table;
|
||||
if (table != main_table)
|
||||
{
|
||||
// We are going to update from this table
|
||||
TABLE *tbl=walk->table=tab->table;
|
||||
/* Don't use KEYREAD optimization on this table */
|
||||
tbl->no_keyread=1;
|
||||
walk=walk->next;
|
||||
uint cnt= table_ref->shared;
|
||||
ORDER group;
|
||||
List<Item> temp_fields= *fields_for_table[cnt];
|
||||
TMP_TABLE_PARAM *tmp_param= tmp_table_param+cnt;
|
||||
|
||||
/*
|
||||
Create a temporary table to store all fields that are changed for this
|
||||
table. The first field in the temporary table is a pointer to the
|
||||
original row so that we can find and update it
|
||||
*/
|
||||
|
||||
/* ok to be on stack as this is not referenced outside of this func */
|
||||
Field_string offset(table->file->ref_length, 0, "offset",
|
||||
table, 1);
|
||||
if (temp_fields.push_front(new Item_field(((Field *) &offset))))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/* Make an unique key over the first field to avoid duplicated updates */
|
||||
bzero((char*) &group, sizeof(group));
|
||||
group.asc= 1;
|
||||
group.item= (Item**) temp_fields.head_ref();
|
||||
|
||||
tmp_param->quick_group=1;
|
||||
tmp_param->field_count=temp_fields.elements;
|
||||
tmp_param->group_parts=1;
|
||||
tmp_param->group_length= table->file->ref_length;
|
||||
if (!(tmp_tables[cnt]=create_tmp_table(thd,
|
||||
tmp_param,
|
||||
temp_fields,
|
||||
(ORDER*) &group, 0, 0, 0,
|
||||
TMP_TABLE_ALL_COLUMNS)))
|
||||
DBUG_RETURN(1);
|
||||
tmp_tables[cnt]->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
multi_update::~multi_update()
|
||||
{
|
||||
int counter = 0;
|
||||
for (table_being_updated=update_tables ;
|
||||
table_being_updated ;
|
||||
counter++, table_being_updated=table_being_updated->next)
|
||||
{
|
||||
TABLE *table=table_being_updated->table;
|
||||
table->no_keyread=0;
|
||||
if (error)
|
||||
table->time_stamp=save_time_stamps[counter];
|
||||
}
|
||||
TABLE_LIST *table;
|
||||
for (table= update_tables ; table; table= table->next)
|
||||
table->table->no_keyread=0;
|
||||
|
||||
if (tmp_tables)
|
||||
for (uint counter = 0; counter < num_updated; counter++)
|
||||
if (tmp_tables[counter])
|
||||
free_tmp_table(thd,tmp_tables[counter]);
|
||||
{
|
||||
for (uint cnt = 0; cnt < table_count; cnt++)
|
||||
{
|
||||
if (tmp_tables[cnt])
|
||||
{
|
||||
free_tmp_table(thd, tmp_tables[cnt]);
|
||||
tmp_table_param[cnt].cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (copy_field)
|
||||
delete [] copy_field;
|
||||
thd->count_cuted_fields=0; // Restore this setting
|
||||
if (!trans_safe)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
|
||||
|
||||
bool multi_update::send_data(List<Item> &values)
|
||||
bool multi_update::send_data(List<Item> ¬_used_values)
|
||||
{
|
||||
List<Item> real_values(values);
|
||||
for (uint counter = 0; counter < fields.elements; counter++)
|
||||
real_values.pop();
|
||||
// We have skipped fields ....
|
||||
if (!num_updated)
|
||||
TABLE_LIST *cur_table;
|
||||
DBUG_ENTER("multi_update::send_data");
|
||||
|
||||
found++;
|
||||
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
|
||||
{
|
||||
for (table_being_updated=update_tables ;
|
||||
table_being_updated ;
|
||||
table_being_updated=table_being_updated->next)
|
||||
{
|
||||
if (!table_being_updated->shared)
|
||||
continue;
|
||||
TABLE *table=table_being_updated->table;
|
||||
TABLE *table= cur_table->table;
|
||||
/* Check if we are using outer join and we didn't find the row */
|
||||
if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
|
||||
return 0;
|
||||
table->file->position(table->record[0]);
|
||||
// Only one table being updated receives a completely different treatment
|
||||
table->status|= STATUS_UPDATED;
|
||||
store_record(table,1);
|
||||
if (fill_record(fields,real_values) || thd->net.report_error)
|
||||
return 1;
|
||||
found++;
|
||||
if (/* compare_record(table, query_id) && */
|
||||
!(error=table->file->update_row(table->record[1], table->record[0])))
|
||||
updated++;
|
||||
table->file->extra(HA_EXTRA_NO_CACHE);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int secure_counter= -1;
|
||||
for (table_being_updated=update_tables ;
|
||||
table_being_updated ;
|
||||
table_being_updated=table_being_updated->next, secure_counter++)
|
||||
{
|
||||
if (!table_being_updated->shared)
|
||||
continue;
|
||||
|
||||
TABLE *table=table_being_updated->table;
|
||||
/* Check if we are using outer join and we didn't find the row */
|
||||
if (table->status & (STATUS_NULL_ROW | STATUS_UPDATED))
|
||||
continue;
|
||||
uint offset= cur_table->shared;
|
||||
table->file->position(table->record[0]);
|
||||
Item *item;
|
||||
List_iterator<Item> it(real_values);
|
||||
List <Item> values_by_table;
|
||||
uint *int_ptr=field_sequence;
|
||||
while ((item= (Item *)it++))
|
||||
{
|
||||
if (*int_ptr++ == (uint) (secure_counter + 1))
|
||||
values_by_table.push_back(item);
|
||||
}
|
||||
// Here I am breaking values as per each table
|
||||
if (secure_counter < 0)
|
||||
if (table == main_table)
|
||||
{
|
||||
table->status|= STATUS_UPDATED;
|
||||
store_record(table,1);
|
||||
if (fill_record(*fields_by_tables[0], values_by_table) ||
|
||||
thd->net.report_error)
|
||||
return 1;
|
||||
found++;
|
||||
if (/*compare_record(table, query_id) && */
|
||||
!(error=table->file->update_row(table->record[1], table->record[0])))
|
||||
if (fill_record(*fields_for_table[offset], *values_for_table[offset]))
|
||||
DBUG_RETURN(1);
|
||||
if (compare_record(table, thd->query_id))
|
||||
{
|
||||
updated++;
|
||||
table->file->extra(HA_EXTRA_NO_CACHE);
|
||||
int error;
|
||||
if (!updated++)
|
||||
{
|
||||
/*
|
||||
Inform the main table that we are going to update the table even
|
||||
while we may be scanning it. This will flush the read cache
|
||||
if it's used.
|
||||
*/
|
||||
main_table->file->extra(HA_EXTRA_PREPARE_FOR_UPDATE);
|
||||
}
|
||||
else
|
||||
if ((error=table->file->update_row(table->record[1],
|
||||
table->record[0])))
|
||||
{
|
||||
table->file->print_error(error,MYF(0));
|
||||
if (!error) error=1;
|
||||
return 1;
|
||||
updated--;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Here we insert into each temporary table
|
||||
values_by_table.push_front(new Item_string((char*) table->file->ref,
|
||||
table->file->ref_length,
|
||||
system_charset_info));
|
||||
fill_record(tmp_tables[secure_counter]->field,values_by_table);
|
||||
error= thd->net.report_error ||
|
||||
write_record(tmp_tables[secure_counter], &(infos[secure_counter]));
|
||||
if (error)
|
||||
int error;
|
||||
TABLE *tmp_table= tmp_tables[offset];
|
||||
fill_record(tmp_table->field+1, *values_for_table[offset]);
|
||||
|
||||
/* Store pointer to row */
|
||||
memcpy((char*) tmp_table->field[0]->ptr,
|
||||
(char*) table->file->ref, table->file->ref_length);
|
||||
/* Write row, ignoring duplicated updates to a row */
|
||||
if ((error= tmp_table->file->write_row(tmp_table->record[0])) &&
|
||||
(error != HA_ERR_FOUND_DUPP_KEY &&
|
||||
error != HA_ERR_FOUND_DUPP_UNIQUE))
|
||||
{
|
||||
error=-1;
|
||||
return 1;
|
||||
if (create_myisam_from_heap(table, tmp_table_param + offset, error, 1))
|
||||
{
|
||||
do_update=0;
|
||||
DBUG_RETURN(1); // Not a table_is_full error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
void multi_update::send_error(uint errcode,const char *err)
|
||||
{
|
||||
|
||||
//TODO error should be sent at the query processing end
|
||||
/* First send error what ever it is ... */
|
||||
::send_error(thd,errcode,err);
|
||||
|
||||
/* reset used flags */
|
||||
// update_tables->table->no_keyread=0;
|
||||
::send_error(&thd->net,errcode,err);
|
||||
|
||||
/* If nothing updated return */
|
||||
if (!updated)
|
||||
|
|
@ -698,99 +706,124 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||
/* Something already updated so we have to invalidate cache */
|
||||
query_cache_invalidate3(thd, update_tables, 1);
|
||||
|
||||
/* Below can happen when thread is killed early ... */
|
||||
if (!table_being_updated)
|
||||
table_being_updated=update_tables;
|
||||
|
||||
/*
|
||||
If rows from the first table only has been updated and it is transactional,
|
||||
just do rollback.
|
||||
The same if all tables are transactional, regardless of where we are.
|
||||
In all other cases do attempt updates ...
|
||||
If all tables that has been updated are trans safe then just do rollback.
|
||||
If not attempt to do remaining updates.
|
||||
*/
|
||||
if ((table_being_updated->table->file->has_transactions() &&
|
||||
table_being_updated == update_tables) || !not_trans_safe)
|
||||
|
||||
if (trans_safe)
|
||||
ha_rollback_stmt(thd);
|
||||
else if (do_update && num_updated)
|
||||
VOID(do_updates(true));
|
||||
else if (do_update && table_count > 1)
|
||||
{
|
||||
/* Add warning here */
|
||||
VOID(do_updates(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int multi_update::do_updates (bool from_send_error)
|
||||
int multi_update::do_updates(bool from_send_error)
|
||||
{
|
||||
int local_error= 0, counter= 0;
|
||||
TABLE_LIST *cur_table;
|
||||
int local_error;
|
||||
ha_rows org_updated;
|
||||
TABLE *table;
|
||||
DBUG_ENTER("do_updates");
|
||||
|
||||
if (from_send_error)
|
||||
do_update= 0; // Don't retry this function
|
||||
for (cur_table= update_tables; cur_table ; cur_table= cur_table->next)
|
||||
{
|
||||
/* Found out table number for 'table_being_updated' */
|
||||
for (TABLE_LIST *aux=update_tables;
|
||||
aux != table_being_updated;
|
||||
aux=aux->next)
|
||||
counter++;
|
||||
table = cur_table->table;
|
||||
if (table == main_table)
|
||||
continue; // Already updated
|
||||
|
||||
org_updated= updated;
|
||||
byte *ref_pos;
|
||||
TABLE *tmp_table= tmp_tables[cur_table->shared];
|
||||
tmp_table->file->extra(HA_EXTRA_CACHE); // Change to read cache
|
||||
table->file->extra(HA_EXTRA_NO_CACHE);
|
||||
|
||||
/*
|
||||
Setup copy functions to copy fields from temporary table
|
||||
*/
|
||||
List_iterator_fast<Item> field_it(*fields_for_table[cur_table->shared]);
|
||||
Field **field= tmp_table->field+1; // Skip row pointer
|
||||
Copy_field *copy_field_ptr= copy_field, *copy_field_end;
|
||||
for ( ; *field ; field++)
|
||||
{
|
||||
Item_field *item= (Item_field* ) field_it++;
|
||||
(copy_field_ptr++)->set(item->field, *field, 0);
|
||||
}
|
||||
else
|
||||
table_being_updated = update_tables;
|
||||
copy_field_end=copy_field_ptr;
|
||||
|
||||
do_update = false;
|
||||
for (table_being_updated=table_being_updated->next;
|
||||
table_being_updated ;
|
||||
table_being_updated=table_being_updated->next, counter++)
|
||||
{
|
||||
if (!table_being_updated->shared)
|
||||
continue;
|
||||
if ((local_error = tmp_table->file->rnd_init(1)))
|
||||
goto err;
|
||||
|
||||
TABLE *table = table_being_updated->table;
|
||||
TABLE *tmp_table=tmp_tables[counter];
|
||||
if (tmp_table->file->extra(HA_EXTRA_NO_CACHE))
|
||||
ref_pos= (byte*) tmp_table->field[0]->ptr;
|
||||
for (;;)
|
||||
{
|
||||
local_error=1;
|
||||
if (thd->killed && trans_safe)
|
||||
goto err;
|
||||
if ((local_error=tmp_table->file->rnd_next(tmp_table->record[0])))
|
||||
{
|
||||
if (local_error == HA_ERR_END_OF_FILE)
|
||||
break;
|
||||
if (local_error == HA_ERR_RECORD_DELETED)
|
||||
continue; // May happen on dup key
|
||||
goto err;
|
||||
}
|
||||
List<Item> list;
|
||||
Field **ptr=tmp_table->field,*field;
|
||||
// This is supposed to be something like insert_fields
|
||||
thd->used_tables|=tmp_table->map;
|
||||
while ((field = *ptr++))
|
||||
{
|
||||
list.push_back((Item *)new Item_field(field));
|
||||
if (field->query_id == thd->query_id)
|
||||
thd->dupp_field=field;
|
||||
field->query_id=thd->query_id;
|
||||
tmp_table->used_keys&=field->part_of_key;
|
||||
}
|
||||
tmp_table->used_fields=tmp_table->fields;
|
||||
local_error=0;
|
||||
list.pop(); // we get position some other way ...
|
||||
local_error = tmp_table->file->rnd_init(1);
|
||||
if (local_error)
|
||||
return local_error;
|
||||
while (!(local_error=tmp_table->file->rnd_next(tmp_table->record[0])) &&
|
||||
(!thd->killed || from_send_error || not_trans_safe))
|
||||
{
|
||||
found++;
|
||||
local_error= table->file->rnd_pos(table->record[0],
|
||||
(byte*) (*(tmp_table->field))->ptr);
|
||||
if (local_error)
|
||||
return local_error;
|
||||
if ((local_error= table->file->rnd_pos(table->record[0], ref_pos)))
|
||||
goto err;
|
||||
table->status|= STATUS_UPDATED;
|
||||
store_record(table,1);
|
||||
local_error= (fill_record(*fields_by_tables[counter + 1],list) ||
|
||||
thd->net.report_error ||
|
||||
/* compare_record(table, query_id) || */
|
||||
table->file->update_row(table->record[1],
|
||||
table->record[0]));
|
||||
if (local_error)
|
||||
|
||||
/* Copy data from temporary table to current table */
|
||||
for (copy_field_ptr=copy_field;
|
||||
copy_field_ptr != copy_field_end;
|
||||
copy_field_ptr++)
|
||||
(*copy_field_ptr->do_copy)(copy_field_ptr);
|
||||
|
||||
if (compare_record(table, thd->query_id))
|
||||
{
|
||||
table->file->print_error(local_error,MYF(0));
|
||||
break;
|
||||
if ((local_error=table->file->update_row(table->record[1],
|
||||
table->record[0])))
|
||||
{
|
||||
if (local_error != HA_ERR_FOUND_DUPP_KEY ||
|
||||
handle_duplicates != DUP_IGNORE)
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
updated++;
|
||||
if (table->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1;
|
||||
}
|
||||
if (local_error == HA_ERR_END_OF_FILE)
|
||||
local_error = 0;
|
||||
}
|
||||
return local_error;
|
||||
|
||||
if (updated != org_updated)
|
||||
{
|
||||
if (table->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1; // Tmp tables forces delay log
|
||||
if (table->file->has_transactions())
|
||||
log_delayed= transactional_tables= 1;
|
||||
else
|
||||
trans_safe= 0; // Can't do safe rollback
|
||||
}
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
|
||||
err:
|
||||
if (!from_send_error)
|
||||
table->file->print_error(local_error,MYF(0));
|
||||
|
||||
if (updated != org_updated)
|
||||
{
|
||||
if (table->tmp_table != NO_TMP_TABLE)
|
||||
log_delayed= 1;
|
||||
if (table->file->has_transactions())
|
||||
log_delayed= transactional_tables= 1;
|
||||
else
|
||||
trans_safe= 0;
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -798,61 +831,57 @@ int multi_update::do_updates (bool from_send_error)
|
|||
|
||||
bool multi_update::send_eof()
|
||||
{
|
||||
thd->proc_info="updating the reference tables";
|
||||
char buff[80];
|
||||
thd->proc_info="updating reference tables";
|
||||
|
||||
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
||||
int local_error = (num_updated) ? do_updates(false) : 0;
|
||||
|
||||
/* reset used flags */
|
||||
#ifndef NOT_USED
|
||||
update_tables->table->no_keyread=0;
|
||||
#endif
|
||||
if (local_error == -1)
|
||||
local_error= 0;
|
||||
int local_error = (table_count) ? do_updates(0) : 0;
|
||||
thd->proc_info= "end";
|
||||
// TODO: Error should be sent at the query processing end
|
||||
if (local_error)
|
||||
send_error(local_error, "An error occured in multi-table update");
|
||||
|
||||
/*
|
||||
Write the SQL statement to the binlog if we updated
|
||||
rows and we succeeded, or also in an error case when there
|
||||
was a non-transaction-safe table involved, since
|
||||
modifications in it cannot be rolled back.
|
||||
rows and we succeeded or if we updated some non
|
||||
transacational tables
|
||||
*/
|
||||
|
||||
if (updated || not_trans_safe)
|
||||
if (updated && (local_error <= 0 || !trans_safe))
|
||||
{
|
||||
mysql_update_log.write(thd,thd->query,thd->query_length);
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
|
||||
|
||||
/*
|
||||
mysql_bin_log is not open if binlogging or replication
|
||||
is not used
|
||||
*/
|
||||
|
||||
if (mysql_bin_log.is_open() && mysql_bin_log.write(&qinfo) &&
|
||||
!not_trans_safe)
|
||||
local_error=1; /* Log write failed: roll back the SQL statement */
|
||||
|
||||
/* Commit or rollback the current SQL statement */
|
||||
VOID(ha_autocommit_or_rollback(thd, local_error > 0));
|
||||
}
|
||||
else
|
||||
local_error= 0; // this can happen only if it is end of file error
|
||||
if (!local_error) // if the above log write did not fail ...
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
char buff[80];
|
||||
Query_log_event qinfo(thd, thd->query, thd->query_length,
|
||||
log_delayed);
|
||||
if (mysql_bin_log.write(&qinfo) && trans_safe)
|
||||
local_error= 1; // Rollback update
|
||||
}
|
||||
if (!log_delayed)
|
||||
thd->options|=OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
|
||||
if (transactional_tables)
|
||||
{
|
||||
if (ha_autocommit_or_rollback(thd, local_error != 0))
|
||||
local_error=1;
|
||||
}
|
||||
|
||||
if (local_error > 0) // if the above log write did not fail ...
|
||||
{
|
||||
/* Safety: If we haven't got an error before (should not happen) */
|
||||
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
|
||||
MYF(0));
|
||||
::send_error(&thd->net);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
sprintf(buff,ER(ER_UPDATE_INFO), (long) found, (long) updated,
|
||||
(long) thd->cuted_fields);
|
||||
if (updated)
|
||||
{
|
||||
query_cache_invalidate3(thd, update_tables, 1);
|
||||
}
|
||||
::send_ok(thd,
|
||||
::send_ok(&thd->net,
|
||||
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated,
|
||||
thd->insert_id_used ? thd->insert_id() : 0L,buff);
|
||||
}
|
||||
thd->count_cuted_fields=0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
113
sql/sql_yacc.yy
113
sql/sql_yacc.yy
|
|
@ -749,7 +749,10 @@ change:
|
|||
LEX *lex = Lex;
|
||||
lex->sql_command = SQLCOM_CHANGE_MASTER;
|
||||
bzero((char*) &lex->mi, sizeof(lex->mi));
|
||||
} master_defs;
|
||||
}
|
||||
master_defs
|
||||
{}
|
||||
;
|
||||
|
||||
master_defs:
|
||||
master_def
|
||||
|
|
@ -830,7 +833,7 @@ create:
|
|||
lex->create_info.table_charset=thd->db_charset?thd->db_charset:default_charset_info;
|
||||
}
|
||||
create2
|
||||
|
||||
{}
|
||||
| CREATE opt_unique_or_fulltext INDEX ident key_alg ON table_ident
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
|
|
@ -1382,8 +1385,9 @@ alter:
|
|||
lex->alter_keys_onoff=LEAVE_AS_IS;
|
||||
lex->simple_alter=1;
|
||||
}
|
||||
alter_list;
|
||||
|
||||
alter_list
|
||||
{}
|
||||
;
|
||||
| ALTER DATABASE ident opt_db_default_character_set
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
|
|
@ -1549,7 +1553,9 @@ repair:
|
|||
lex->sql_command = SQLCOM_REPAIR;
|
||||
lex->check_opt.init();
|
||||
}
|
||||
table_list opt_mi_repair_type;
|
||||
table_list opt_mi_repair_type
|
||||
{}
|
||||
;
|
||||
|
||||
opt_mi_repair_type:
|
||||
/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
|
||||
|
|
@ -1571,7 +1577,9 @@ analyze:
|
|||
lex->sql_command = SQLCOM_ANALYZE;
|
||||
lex->check_opt.init();
|
||||
}
|
||||
table_list opt_mi_check_type;
|
||||
table_list opt_mi_check_type
|
||||
{}
|
||||
;
|
||||
|
||||
check:
|
||||
CHECK_SYM table_or_tables
|
||||
|
|
@ -1580,7 +1588,9 @@ check:
|
|||
lex->sql_command = SQLCOM_CHECK;
|
||||
lex->check_opt.init();
|
||||
}
|
||||
table_list opt_mi_check_type;
|
||||
table_list opt_mi_check_type
|
||||
{}
|
||||
;
|
||||
|
||||
opt_mi_check_type:
|
||||
/* empty */ { Lex->check_opt.flags = T_MEDIUM; }
|
||||
|
|
@ -1604,14 +1614,18 @@ optimize:
|
|||
lex->sql_command = SQLCOM_OPTIMIZE;
|
||||
lex->check_opt.init();
|
||||
}
|
||||
table_list opt_mi_check_type;
|
||||
table_list opt_mi_check_type
|
||||
{}
|
||||
;
|
||||
|
||||
rename:
|
||||
RENAME table_or_tables
|
||||
{
|
||||
Lex->sql_command=SQLCOM_RENAME_TABLE;
|
||||
}
|
||||
table_to_table_list;
|
||||
table_to_table_list
|
||||
{}
|
||||
;
|
||||
|
||||
table_to_table_list:
|
||||
table_to_table
|
||||
|
|
@ -1642,7 +1656,7 @@ select_init:
|
|||
{
|
||||
LEX *lex= Lex;
|
||||
SELECT_LEX_NODE * sel= lex->current_select;
|
||||
if (sel->set_braces(true))
|
||||
if (sel->set_braces(1))
|
||||
{
|
||||
send_error(lex->thd, ER_SYNTAX_ERROR);
|
||||
YYABORT;
|
||||
|
|
@ -1656,7 +1670,7 @@ select_init2:
|
|||
select_part2
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (lex->current_select->set_braces(false))
|
||||
if (lex->current_select->set_braces(0))
|
||||
{
|
||||
send_error(lex->thd, ER_SYNTAX_ERROR);
|
||||
YYABORT;
|
||||
|
|
@ -2482,7 +2496,7 @@ join_table:
|
|||
select_derived:
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->derived_tables= true;
|
||||
lex->derived_tables= 1;
|
||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE ||
|
||||
mysql_new_select(lex, 1))
|
||||
YYABORT;
|
||||
|
|
@ -2618,7 +2632,7 @@ olap_opt:
|
|||
| WITH CUBE_SYM
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->olap = true;
|
||||
lex->olap= 1;
|
||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
||||
{
|
||||
net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
|
||||
|
|
@ -2632,7 +2646,7 @@ olap_opt:
|
|||
| WITH ROLLUP_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
lex->olap= true;
|
||||
lex->olap= 1;
|
||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
||||
{
|
||||
net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
|
||||
|
|
@ -2699,6 +2713,7 @@ limit_clause:
|
|||
}
|
||||
}
|
||||
limit_options
|
||||
{}
|
||||
;
|
||||
|
||||
limit_options:
|
||||
|
|
@ -2753,7 +2768,7 @@ procedure_clause:
|
|||
lex->proc_list.elements=0;
|
||||
lex->proc_list.first=0;
|
||||
lex->proc_list.next= (byte**) &lex->proc_list.first;
|
||||
if (add_proc_to_list(new Item_field(NULL,NULL,$2.str)))
|
||||
if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
|
||||
YYABORT;
|
||||
Lex->safe_to_cache_query=0;
|
||||
}
|
||||
|
|
@ -2771,10 +2786,11 @@ procedure_list2:
|
|||
procedure_item:
|
||||
remember_name expr
|
||||
{
|
||||
if (add_proc_to_list($2))
|
||||
LEX *lex= Lex;
|
||||
if (add_proc_to_list(lex->thd, $2))
|
||||
YYABORT;
|
||||
if (!$2->name)
|
||||
$2->set_name($1,(uint) ((char*) Lex->tok_end - $1));
|
||||
$2->set_name($1,(uint) ((char*) lex->tok_end - $1));
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -2842,7 +2858,10 @@ do: DO_SYM
|
|||
if (!(lex->insert_list = new List_item))
|
||||
YYABORT;
|
||||
}
|
||||
values;
|
||||
values
|
||||
{}
|
||||
;
|
||||
|
||||
/*
|
||||
Drop : delete tables or index
|
||||
*/
|
||||
|
|
@ -2928,6 +2947,8 @@ replace:
|
|||
Select->set_lock_for_tables($3);
|
||||
}
|
||||
insert_field_spec
|
||||
{}
|
||||
{}
|
||||
;
|
||||
|
||||
insert_lock_option:
|
||||
|
|
@ -3122,13 +3143,15 @@ single_multi:
|
|||
YYABORT;
|
||||
}
|
||||
where_clause opt_order_clause
|
||||
delete_limit_clause
|
||||
delete_limit_clause {}
|
||||
| table_wild_list
|
||||
{ mysql_init_multi_delete(Lex); }
|
||||
FROM join_table_list where_clause
|
||||
| FROM table_wild_list
|
||||
{ mysql_init_multi_delete(Lex); }
|
||||
USING join_table_list where_clause;
|
||||
USING join_table_list where_clause
|
||||
{}
|
||||
;
|
||||
|
||||
table_wild_list:
|
||||
table_wild_one {}
|
||||
|
|
@ -3184,7 +3207,9 @@ show: SHOW
|
|||
lex->wild=0;
|
||||
bzero((char*) &lex->create_info,sizeof(lex->create_info));
|
||||
}
|
||||
show_param;
|
||||
show_param
|
||||
{}
|
||||
;
|
||||
|
||||
show_param:
|
||||
DATABASES wild
|
||||
|
|
@ -3354,13 +3379,13 @@ describe:
|
|||
if (!Select->add_table_to_list($2, NULL,0))
|
||||
YYABORT;
|
||||
}
|
||||
opt_describe_column
|
||||
opt_describe_column {}
|
||||
| describe_command { Lex->describe=1; } select
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->select_lex.options|= SELECT_DESCRIBE;
|
||||
};
|
||||
|
||||
}
|
||||
;
|
||||
|
||||
describe_command:
|
||||
DESC
|
||||
|
|
@ -3381,14 +3406,16 @@ flush:
|
|||
LEX *lex=Lex;
|
||||
lex->sql_command= SQLCOM_FLUSH; lex->type=0;
|
||||
}
|
||||
flush_options;
|
||||
flush_options
|
||||
{}
|
||||
;
|
||||
|
||||
flush_options:
|
||||
flush_options ',' flush_option
|
||||
| flush_option;
|
||||
|
||||
flush_option:
|
||||
table_or_tables { Lex->type|= REFRESH_TABLES; } opt_table_list
|
||||
table_or_tables { Lex->type|= REFRESH_TABLES; } opt_table_list {}
|
||||
| TABLES WITH READ_SYM LOCK_SYM { Lex->type|= REFRESH_TABLES | REFRESH_READ_LOCK; }
|
||||
| QUERY_SYM CACHE_SYM { Lex->type|= REFRESH_QUERY_CACHE_FREE; }
|
||||
| HOSTS_SYM { Lex->type|= REFRESH_HOSTS; }
|
||||
|
|
@ -3409,7 +3436,10 @@ reset:
|
|||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command= SQLCOM_RESET; lex->type=0;
|
||||
} reset_options;
|
||||
} reset_options
|
||||
{}
|
||||
;
|
||||
|
||||
reset_options:
|
||||
reset_options ',' reset_option
|
||||
| reset_option;
|
||||
|
|
@ -3840,7 +3870,9 @@ set:
|
|||
lex->option_type=OPT_DEFAULT;
|
||||
lex->var_list.empty();
|
||||
}
|
||||
option_value_list;
|
||||
option_value_list
|
||||
{}
|
||||
;
|
||||
|
||||
opt_option:
|
||||
/* empty */ {}
|
||||
|
|
@ -3964,7 +3996,9 @@ lock:
|
|||
{
|
||||
Lex->sql_command=SQLCOM_LOCK_TABLES;
|
||||
}
|
||||
table_lock_list;
|
||||
table_lock_list
|
||||
{}
|
||||
;
|
||||
|
||||
table_or_tables:
|
||||
TABLE_SYM
|
||||
|
|
@ -4074,7 +4108,9 @@ revoke:
|
|||
lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
|
||||
bzero((char*) &lex->mqh, sizeof(lex->mqh));
|
||||
}
|
||||
grant_privileges ON opt_table FROM user_list;
|
||||
grant_privileges ON opt_table FROM user_list
|
||||
{}
|
||||
;
|
||||
|
||||
grant:
|
||||
GRANT
|
||||
|
|
@ -4090,7 +4126,9 @@ grant:
|
|||
bzero(&(lex->mqh),sizeof(lex->mqh));
|
||||
}
|
||||
grant_privileges ON opt_table TO_SYM user_list
|
||||
require_clause grant_options;
|
||||
require_clause grant_options
|
||||
{}
|
||||
;
|
||||
|
||||
grant_privileges:
|
||||
grant_privilege_list {}
|
||||
|
|
@ -4103,10 +4141,10 @@ grant_privilege_list:
|
|||
| grant_privilege_list ',' grant_privilege;
|
||||
|
||||
grant_privilege:
|
||||
SELECT_SYM { Lex->which_columns = SELECT_ACL;} opt_column_list
|
||||
| INSERT { Lex->which_columns = INSERT_ACL;} opt_column_list
|
||||
| UPDATE_SYM { Lex->which_columns = UPDATE_ACL; } opt_column_list
|
||||
| REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list
|
||||
SELECT_SYM { Lex->which_columns = SELECT_ACL;} opt_column_list {}
|
||||
| INSERT { Lex->which_columns = INSERT_ACL;} opt_column_list {}
|
||||
| UPDATE_SYM { Lex->which_columns = UPDATE_ACL; } opt_column_list {}
|
||||
| REFERENCES { Lex->which_columns = REFERENCES_ACL;} opt_column_list {}
|
||||
| DELETE_SYM { Lex->grant |= DELETE_ACL;}
|
||||
| USAGE {}
|
||||
| INDEX { Lex->grant |= INDEX_ACL;}
|
||||
|
|
@ -4333,7 +4371,8 @@ grant_option:
|
|||
;
|
||||
|
||||
begin:
|
||||
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work;
|
||||
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work {}
|
||||
;
|
||||
|
||||
opt_work:
|
||||
/* empty */ {}
|
||||
|
|
@ -4376,7 +4415,7 @@ union_list:
|
|||
YYABORT;
|
||||
lex->current_select->linkage=UNION_TYPE;
|
||||
}
|
||||
select_init
|
||||
select_init {}
|
||||
;
|
||||
|
||||
union_opt:
|
||||
|
|
|
|||
13
sql/table.h
13
sql/table.h
|
|
@ -118,8 +118,7 @@ struct st_table {
|
|||
table_map map; /* ID bit of table (1,2,4,8,16...) */
|
||||
ulong version,flush_version;
|
||||
uchar *null_flags;
|
||||
IO_CACHE *io_cache; /* If sorted trough file*/
|
||||
byte *record_pointers; /* If sorted in memory */
|
||||
IO_CACHE *io_cache; /* If sorted trough filebyte *record_pointers; /* If sorted in memory */
|
||||
ha_rows found_records; /* How many records in sort */
|
||||
ORDER *group;
|
||||
ha_rows quick_rows[MAX_KEY];
|
||||
|
|
@ -127,11 +126,13 @@ struct st_table {
|
|||
key_part_map const_key_parts[MAX_KEY];
|
||||
ulong query_id;
|
||||
|
||||
uint temp_pool_slot;
|
||||
|
||||
union /* Temporary variables */
|
||||
{
|
||||
uint temp_pool_slot; /* Used by intern temp tables */
|
||||
struct st_table_list *pos_in_table_list;
|
||||
};
|
||||
/* number of select if it is derived table */
|
||||
uint derived_select_number;
|
||||
|
||||
THD *in_use; /* Which thread uses this */
|
||||
struct st_table *next,*prev;
|
||||
};
|
||||
|
|
@ -161,10 +162,10 @@ typedef struct st_table_list
|
|||
GRANT_INFO grant;
|
||||
thr_lock_type lock_type;
|
||||
uint outer_join; /* Which join type */
|
||||
uint shared; /* Used in union or in multi-upd */
|
||||
uint32 db_length, real_name_length;
|
||||
bool straight; /* optimize with prev table */
|
||||
bool updating; /* for replicate-do/ignore table */
|
||||
bool shared; /* Used twice in union */
|
||||
bool do_redirect; /* To get the struct in UNION's */
|
||||
} TABLE_LIST;
|
||||
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ static bool make_empty_rec(File file,enum db_type table_type,
|
|||
if (field->def &&
|
||||
(regfield->real_type() != FIELD_TYPE_YEAR ||
|
||||
field->def->val_int() != 0))
|
||||
(void) field->def->save_in_field(regfield);
|
||||
(void) field->def->save_in_field(regfield, 1);
|
||||
else if (regfield->real_type() == FIELD_TYPE_ENUM &&
|
||||
(field->flags & NOT_NULL_FLAG))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@ function (const char *nptr,char **endptr,int base)
|
|||
}
|
||||
|
||||
/* Check for a sign. */
|
||||
negative= 0;
|
||||
if (*s == '-')
|
||||
{
|
||||
negative = 1;
|
||||
|
|
@ -110,11 +111,9 @@ function (const char *nptr,char **endptr,int base)
|
|||
}
|
||||
else if (*s == '+')
|
||||
{
|
||||
negative = 0;
|
||||
++s;
|
||||
}
|
||||
else
|
||||
negative = 0;
|
||||
|
||||
|
||||
if (base == 16 && s[0] == '0' && my_toupper (system_charset_info, s[1]) == 'X')
|
||||
s += 2;
|
||||
|
|
|
|||
|
|
@ -17,16 +17,30 @@
|
|||
# History:
|
||||
#
|
||||
# When Who What
|
||||
# -------------------------------------------------------------
|
||||
# ------------------------------------------------------------------
|
||||
# 2001-09-16 Marc Liyanage First version
|
||||
# 2001-11-18 Marc Liyanage Improved configure directory options
|
||||
#
|
||||
|
||||
use strict;
|
||||
use DirHandle;
|
||||
|
||||
my $data = {};
|
||||
|
||||
$data->{PREFIX_DIR} = "/usr/local";
|
||||
$data->{CONFIG} = "--prefix=$data->{PREFIX_DIR} --with-innodb";
|
||||
$data->{PREFIX_DIR} = "/usr/local/mysql";
|
||||
$data->{CONFIG} = join(" ",
|
||||
"--prefix=$data->{PREFIX_DIR}",
|
||||
"--localstatedir=$data->{PREFIX_DIR}/data",
|
||||
"--libdir=$data->{PREFIX_DIR}/lib",
|
||||
"--includedir=$data->{PREFIX_DIR}/include",
|
||||
"--with-named-z-libs=/usr/local/libz.a",
|
||||
"--with-innodb",
|
||||
"--with-server-suffix='-entropy.ch'",
|
||||
"--with-comment='http://www.entropy.ch/software/macosx/mysql/'",
|
||||
"--with-mysqld-user=mysql",
|
||||
"--enable-assembler",
|
||||
"CFLAGS=\"-DHAVE_BROKEN_REALPATH -lncurses\"",
|
||||
);
|
||||
|
||||
|
||||
|
||||
|
|
@ -177,8 +191,7 @@ sub make_binary_distribution {
|
|||
|
||||
|
||||
# Now we build a fake /usr/local directory hierarchy.
|
||||
# This will be fed to the pax tool to create
|
||||
# the archive.
|
||||
# This will be fed to the pax tool to create the archive.
|
||||
#
|
||||
sub create_pax_root {
|
||||
|
||||
|
|
@ -190,7 +203,7 @@ sub create_pax_root {
|
|||
chdir($data->{PAXROOT_DIR});
|
||||
my $tarfile = "$data->{OLDWD}/$data->{BINARY_TARBALL_FILENAME}";
|
||||
|
||||
if(system("tar -xzf $tarfile")) {
|
||||
if (system("tar -xzf $tarfile")) {
|
||||
abort($data, "Unable to extract $tarfile inside $data->{PAXROOT_DIR}");
|
||||
}
|
||||
|
||||
|
|
@ -213,14 +226,35 @@ sub create_pax_root {
|
|||
|
||||
# First create the symlinks in the bin directory
|
||||
#
|
||||
# 2001-02-13: we no longer use symlinks for the binaries, we
|
||||
# use small dummy scripts instead because the
|
||||
# mysql scripts do a lot of guesswork with their
|
||||
# own path and that will not work when called via the symlink
|
||||
#
|
||||
# symlink("../mysql/bin/$_", "$_") foreach (grep {$_ !~ /^\.+$/} DirHandle->new("../mysql/bin")->read());
|
||||
|
||||
chdir("bin");
|
||||
symlink("../mysql/bin/$_", "$_") foreach (grep {$_ !~ /^\.+$/} DirHandle->new("../mysql/bin")->read());
|
||||
|
||||
foreach my $command (grep {$_ !~ /^\.+$/} DirHandle->new("../mysql/bin")->read()) {
|
||||
|
||||
my $scriptcode = qq+#!/bin/sh\n# Part of the entropy.ch mysql package\ncd /usr/local/mysql/\nexec ./bin/$command "\$\@"\n+;
|
||||
open(SCRIPTFILE, ">$command") or die "Unable to write open $command\n";
|
||||
print SCRIPTFILE $scriptcode;
|
||||
close(SCRIPTFILE);
|
||||
chmod(0755, $command);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Now include the man pages. Two problems here:
|
||||
# 1.) the make_binary_distribution script does not seem
|
||||
# to include the man pages, so we have to copy them over
|
||||
# now.
|
||||
# now. [outdated, was fixed by MySQL!]
|
||||
# 2.) The man pages could be in different sections, so
|
||||
# we have to recursively copy *and* symlink them.
|
||||
#
|
||||
|
|
@ -230,7 +264,7 @@ sub create_pax_root {
|
|||
# arrays which in turn will be stored in a hash, using
|
||||
# the section numbers as hash keys.
|
||||
#
|
||||
chdir($data->{OLDWD});
|
||||
chdir("$data->{PAXROOT_DIR}/mysql");
|
||||
my %man_sections;
|
||||
foreach my $manpage (grep {$_ =~ /^.+\.(\d+)$/} DirHandle->new("man")->read()) {
|
||||
|
||||
|
|
@ -249,14 +283,12 @@ sub create_pax_root {
|
|||
|
||||
foreach my $section (keys(%man_sections)) {
|
||||
|
||||
system("mkdir -p $data->{PAXROOT_DIR}/mysql/man/man$section/");
|
||||
system("mkdir -p man$section");
|
||||
chdir("man$section");
|
||||
|
||||
foreach my $manpage (@{$man_sections{$section}}) {
|
||||
|
||||
system("cp $data->{OLDWD}/man/$manpage $data->{PAXROOT_DIR}/mysql/man/man$section/");
|
||||
symlink("../../../mysql/man/man$section/$manpage", $manpage)
|
||||
symlink("../../../mysql/man/$manpage", $manpage)
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -265,6 +297,35 @@ sub create_pax_root {
|
|||
}
|
||||
|
||||
|
||||
|
||||
# Fix up the library and lib directories. They are packed up wrong in the
|
||||
# binary distribution tarball.
|
||||
#
|
||||
# (no longer needed as of 3.23.47)
|
||||
# (oops, still needed because 3.23.47 is broken...)
|
||||
#
|
||||
# if (-d "$data->{PAXROOT_DIR}/mysql/lib/mysql") {
|
||||
# abort($data, "$data->{PAXROOT_DIR}/mysql/lib/mysql exists, layout has changed!");
|
||||
# }
|
||||
# chdir("$data->{PAXROOT_DIR}/mysql/lib/");
|
||||
# system("mkdir -p mysql");
|
||||
# system("mv * mysql");
|
||||
|
||||
# if (-d "$data->{PAXROOT_DIR}/mysql/include/mysql") {
|
||||
# abort($data, "$data->{PAXROOT_DIR}/mysql/include/mysql exists, layout has changed!");
|
||||
# }
|
||||
# chdir("$data->{PAXROOT_DIR}/mysql/include/");
|
||||
# system("mkdir -p mysql");
|
||||
# system("mv * mysql");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -310,7 +371,7 @@ sub create_package {
|
|||
my $size_compressed = `du -sk $data->{PACKAGE_DIR} | cut -f 1`;
|
||||
chomp($size_compressed);
|
||||
|
||||
my $numfiles = `find /tmp/mysql-3.23.42-paxroot/ | wc -l`;
|
||||
my $numfiles = `find /tmp/mysql-$data->{VERSION}-paxroot | wc -l`;
|
||||
$numfiles--;
|
||||
|
||||
open(SIZESFILE, ">$data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.sizes") or abort("Unable to write open sizes file $data->{PKG_RESOURCES_DIR}/mysql-$data->{VERSION}.sizes");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
# Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB
|
||||
# This file is public domain and comes with NO WARRANTY of any kind
|
||||
|
||||
# Mysql daemon start/stop script.
|
||||
# MySQL daemon start/stop script.
|
||||
|
||||
# Usually this is put in /etc/init.d (at least on machines SYSV R4 based
|
||||
# systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql.
|
||||
|
|
@ -20,17 +20,17 @@
|
|||
# Required-Stop: $local_fs $network $remote_fs
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 3 5
|
||||
# Short-Description: start and stop MySLQ
|
||||
# Short-Description: start and stop MySQL
|
||||
# Description: MySQL is a very fast and reliable SQL database engine.
|
||||
### END INIT INFO
|
||||
|
||||
# If you install MySQL on some other places than @prefix@, then you
|
||||
# have to do one of the following thing for this script to work:
|
||||
# have to do one of the following things for this script to work:
|
||||
#
|
||||
# - Run this script from the MySQL installation directory
|
||||
# - Run this script from within the MySQL installation directory
|
||||
# - Create a /etc/my.cnf file with the following information:
|
||||
# [mysqld]
|
||||
# basedir=path-to-mysql-installation-directory
|
||||
# basedir=<path-to-mysql-installation-directory>
|
||||
# - Add the above to any other configuration file (for example ~/.my.ini)
|
||||
# and copy my_print_defaults to /usr/bin
|
||||
# - Add the path to the mysql-installation-directory to the basedir variable
|
||||
|
|
@ -79,7 +79,8 @@ parse_arguments() {
|
|||
done
|
||||
}
|
||||
|
||||
# Get arguments from the my.cnf file, groups [mysqld] and [mysql_server]
|
||||
# Get arguments from the my.cnf file,
|
||||
# groups [mysqld] [mysql_server] and [mysql.server]
|
||||
if test -x ./bin/my_print_defaults
|
||||
then
|
||||
print_defaults="./bin/my_print_defaults"
|
||||
|
|
@ -117,7 +118,7 @@ else
|
|||
test -z "$print_defaults" && print_defaults="my_print_defaults"
|
||||
fi
|
||||
|
||||
parse_arguments `$print_defaults $defaults mysqld mysql_server`
|
||||
parse_arguments `$print_defaults mysqld mysql_server mysql.server`
|
||||
|
||||
# Safeguard (relative paths, core dumps..)
|
||||
cd $basedir
|
||||
|
|
@ -154,7 +155,7 @@ case "$mode" in
|
|||
sleep 1
|
||||
while [ -s $pid_file -a "$flags" != aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ]
|
||||
do
|
||||
[ -z "$flags" ] && echo -n "Wait for mysqld to exit" || echo -n "."
|
||||
[ -z "$flags" ] && echo "Wait for mysqld to exit\c" || echo ".\c"
|
||||
flags=a$flags
|
||||
sleep 1
|
||||
done
|
||||
|
|
|
|||
|
|
@ -134,6 +134,9 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
|
|||
vio->sd);
|
||||
#if !defined(___WIN__) && !defined(__EMX__) && !defined(OS2)
|
||||
#if !defined(NO_FCNTL_NONBLOCK)
|
||||
#if defined(__FreeBSD__)
|
||||
fcntl(sd, F_SETFL, vio->fcntl_mode); /* Yahoo! FreeBSD patch */
|
||||
#endif
|
||||
vio->fcntl_mode = fcntl(sd, F_GETFL);
|
||||
#elif defined(HAVE_SYS_IOCTL_H) /* hpux */
|
||||
/* Non blocking sockets doesn't work good on HPUX 11.0 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue