Merge kboortz@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into mysql.com:/Users/kent/mysql/bk/mysql-5.1-new


mysql-test/r/sp.result:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sql_class.h:
  Auto merged
This commit is contained in:
unknown 2005-12-12 12:30:18 +01:00
commit 031ec5d2bd
1049 changed files with 35918 additions and 168064 deletions

View file

@ -133,137 +133,107 @@ autom4te.cache/*
autom4te.cache/output.0 autom4te.cache/output.0
autom4te.cache/requests autom4te.cache/requests
autom4te.cache/traces.0 autom4te.cache/traces.0
bdb/*.ds? storage/bdb/*.ds?
bdb/*.vcproj storage/bdb/*.vcproj
bdb/README storage/bdb/README
bdb/btree/btree_auto.c storage/bdb/btree/btree_auto.c
bdb/build_unix/* storage/bdb/build_unix/*
bdb/build_vxworks/db.h storage/bdb/build_vxworks/db.h
bdb/build_vxworks/db_int.h storage/bdb/build_vxworks/db_int.h
bdb/build_win32/db.h storage/bdb/build_win32/db.h
bdb/build_win32/db_archive.dsp storage/bdb/build_win32/db_archive.dsp
bdb/build_win32/db_checkpoint.dsp storage/bdb/build_win32/db_checkpoint.dsp
bdb/build_win32/db_config.h storage/bdb/build_win32/db_config.h
bdb/build_win32/db_cxx.h storage/bdb/build_win32/db_cxx.h
bdb/build_win32/db_deadlock.dsp storage/bdb/build_win32/db_deadlock.dsp
bdb/build_win32/db_dll.dsp storage/bdb/build_win32/db_dll.dsp
bdb/build_win32/db_dump.dsp storage/bdb/build_win32/db_dump.dsp
bdb/build_win32/db_int.h storage/bdb/build_win32/db_int.h
bdb/build_win32/db_java.dsp storage/bdb/build_win32/db_java.dsp
bdb/build_win32/db_load.dsp storage/bdb/build_win32/db_load.dsp
bdb/build_win32/db_perf.dsp storage/bdb/build_win32/db_perf.dsp
bdb/build_win32/db_printlog.dsp storage/bdb/build_win32/db_printlog.dsp
bdb/build_win32/db_recover.dsp storage/bdb/build_win32/db_recover.dsp
bdb/build_win32/db_stat.dsp storage/bdb/build_win32/db_stat.dsp
bdb/build_win32/db_static.dsp storage/bdb/build_win32/db_static.dsp
bdb/build_win32/db_tcl.dsp storage/bdb/build_win32/db_tcl.dsp
bdb/build_win32/db_test.dsp storage/bdb/build_win32/db_test.dsp
bdb/build_win32/db_upgrade.dsp storage/bdb/build_win32/db_upgrade.dsp
bdb/build_win32/db_verify.dsp storage/bdb/build_win32/db_verify.dsp
bdb/build_win32/ex_access.dsp storage/bdb/build_win32/ex_access.dsp
bdb/build_win32/ex_btrec.dsp storage/bdb/build_win32/ex_btrec.dsp
bdb/build_win32/ex_env.dsp storage/bdb/build_win32/ex_env.dsp
bdb/build_win32/ex_lock.dsp storage/bdb/build_win32/ex_lock.dsp
bdb/build_win32/ex_mpool.dsp storage/bdb/build_win32/ex_mpool.dsp
bdb/build_win32/ex_tpcb.dsp storage/bdb/build_win32/ex_tpcb.dsp
bdb/build_win32/excxx_access.dsp storage/bdb/build_win32/excxx_access.dsp
bdb/build_win32/excxx_btrec.dsp storage/bdb/build_win32/excxx_btrec.dsp
bdb/build_win32/excxx_env.dsp storage/bdb/build_win32/excxx_env.dsp
bdb/build_win32/excxx_lock.dsp storage/bdb/build_win32/excxx_lock.dsp
bdb/build_win32/excxx_mpool.dsp storage/bdb/build_win32/excxx_mpool.dsp
bdb/build_win32/excxx_tpcb.dsp storage/bdb/build_win32/excxx_tpcb.dsp
bdb/build_win32/include.tcl storage/bdb/build_win32/include.tcl
bdb/build_win32/libdb.def storage/bdb/build_win32/libdb.def
bdb/build_win32/libdb.rc storage/bdb/build_win32/libdb.rc
bdb/db/crdel_auto.c storage/bdb/db/crdel_auto.c
bdb/db/db_auto.c storage/bdb/db/db_auto.c
bdb/dbinc_auto/*.* storage/bdb/dbinc_auto/*.*
bdb/dbreg/dbreg_auto.c storage/bdb/dbreg/dbreg_auto.c
bdb/dist/autom4te-2.53.cache/* storage/bdb/dist/autom4te-2.53.cache/*
bdb/dist/autom4te-2.53.cache/output.0 storage/bdb/dist/autom4te-2.53.cache/output.0
bdb/dist/autom4te-2.53.cache/requests storage/bdb/dist/autom4te-2.53.cache/requests
bdb/dist/autom4te-2.53.cache/traces.0 storage/bdb/dist/autom4te-2.53.cache/traces.0
bdb/dist/autom4te.cache/* storage/bdb/dist/autom4te.cache/*
bdb/dist/autom4te.cache/output.0 storage/bdb/dist/autom4te.cache/output.0
bdb/dist/autom4te.cache/requests storage/bdb/dist/autom4te.cache/requests
bdb/dist/autom4te.cache/traces.0 storage/bdb/dist/autom4te.cache/traces.0
bdb/dist/config.hin storage/bdb/dist/config.hin
bdb/dist/configure storage/bdb/dist/configure
bdb/dist/tags storage/bdb/dist/tags
bdb/dist/template/db_server_proc storage/bdb/dist/template/db_server_proc
bdb/dist/template/gen_client_ret storage/bdb/dist/template/gen_client_ret
bdb/dist/template/rec_btree storage/bdb/dist/template/rec_btree
bdb/dist/template/rec_crdel storage/bdb/dist/template/rec_crdel
bdb/dist/template/rec_db storage/bdb/dist/template/rec_db
bdb/dist/template/rec_dbreg storage/bdb/dist/template/rec_dbreg
bdb/dist/template/rec_fileops storage/bdb/dist/template/rec_fileops
bdb/dist/template/rec_hash storage/bdb/dist/template/rec_hash
bdb/dist/template/rec_log storage/bdb/dist/template/rec_log
bdb/dist/template/rec_qam storage/bdb/dist/template/rec_qam
bdb/dist/template/rec_txn storage/bdb/dist/template/rec_txn
bdb/examples_c/ex_apprec/ex_apprec_auto.c storage/bdb/fileops/fileops_auto.c
bdb/examples_c/ex_apprec/ex_apprec_auto.h storage/bdb/hash/hash_auto.c
bdb/examples_c/ex_apprec/ex_apprec_template storage/bdb/include/btree_auto.h
bdb/examples_java storage/bdb/include/btree_ext.h
bdb/fileops/fileops_auto.c storage/bdb/include/clib_ext.h
bdb/hash/hash_auto.c storage/bdb/include/common_ext.h
bdb/include/btree_auto.h storage/bdb/include/crdel_auto.h
bdb/include/btree_ext.h storage/bdb/include/db_auto.h
bdb/include/clib_ext.h storage/bdb/include/db_ext.h
bdb/include/common_ext.h storage/bdb/include/db_server.h
bdb/include/crdel_auto.h storage/bdb/include/env_ext.h
bdb/include/db_auto.h storage/bdb/include/gen_client_ext.h
bdb/include/db_ext.h storage/bdb/include/gen_server_ext.h
bdb/include/db_server.h storage/bdb/include/hash_auto.h
bdb/include/env_ext.h storage/bdb/include/hash_ext.h
bdb/include/gen_client_ext.h storage/bdb/include/lock_ext.h
bdb/include/gen_server_ext.h storage/bdb/include/log_auto.h
bdb/include/hash_auto.h storage/bdb/include/log_ext.h
bdb/include/hash_ext.h storage/bdb/include/mp_ext.h
bdb/include/lock_ext.h storage/bdb/include/mutex_ext.h
bdb/include/log_auto.h storage/bdb/include/os_ext.h
bdb/include/log_ext.h storage/bdb/include/qam_auto.h
bdb/include/mp_ext.h storage/bdb/include/qam_ext.h
bdb/include/mutex_ext.h storage/bdb/include/rpc_client_ext.h
bdb/include/os_ext.h storage/bdb/include/rpc_server_ext.h
bdb/include/qam_auto.h storage/bdb/include/tcl_ext.h
bdb/include/qam_ext.h storage/bdb/include/txn_auto.h
bdb/include/rpc_client_ext.h storage/bdb/include/txn_ext.h
bdb/include/rpc_server_ext.h storage/bdb/include/xa_ext.h
bdb/include/tcl_ext.h storage/bdb/log/log_auto.c
bdb/include/txn_auto.h storage/bdb/qam/qam_auto.c
bdb/include/txn_ext.h storage/bdb/txn/txn_auto.c
bdb/include/xa_ext.h storage/bdb/txn/txn_autop.c
bdb/java/src/com/sleepycat/db/Db.java
bdb/java/src/com/sleepycat/db/DbBtreeStat.java
bdb/java/src/com/sleepycat/db/DbConstants.java
bdb/java/src/com/sleepycat/db/DbHashStat.java
bdb/java/src/com/sleepycat/db/DbLockStat.java
bdb/java/src/com/sleepycat/db/DbLogStat.java
bdb/java/src/com/sleepycat/db/DbMpoolFStat.java
bdb/java/src/com/sleepycat/db/DbQueueStat.java
bdb/java/src/com/sleepycat/db/DbRepStat.java
bdb/java/src/com/sleepycat/db/DbTxnStat.java
bdb/libdb_java/java_stat_auto.c
bdb/libdb_java/java_stat_auto.h
bdb/log/log_auto.c
bdb/qam/qam_auto.c
bdb/rpc_client/db_server_clnt.c
bdb/rpc_client/gen_client.c
bdb/rpc_server/c/db_server_proc.c
bdb/rpc_server/c/db_server_proc.sed
bdb/rpc_server/c/db_server_svc.c
bdb/rpc_server/c/db_server_xdr.c
bdb/rpc_server/c/gen_db_server.c
bdb/rpc_server/db_server.x
bdb/rpc_server/db_server_proc.sed
bdb/rpc_server/db_server_svc.c
bdb/rpc_server/db_server_xdr.c
bdb/rpc_server/gen_db_server.c
bdb/test/TESTS
bdb/test/include.tcl
bdb/test/logtrack.list
bdb/txn/txn_auto.c
binary/* binary/*
bkpull.log bkpull.log
bkpull.log* bkpull.log*
@ -1688,3 +1658,4 @@ vio/viotest-sslconnect.cpp
vio/viotest.cpp vio/viotest.cpp
zlib/*.ds? zlib/*.ds?
zlib/*.vcproj zlib/*.vcproj
client/mysqlslap

View file

@ -2,7 +2,7 @@
#shift #shift
FROM=$USER@mysql.com FROM=$USER@mysql.com
INTERNALS=internals@lists.mysql.com COMMITS=commits@lists.mysql.com
DOCS=docs-commit@mysql.com DOCS=docs-commit@mysql.com
LIMIT=10000 LIMIT=10000
VERSION="5.1" VERSION="5.1"
@ -61,14 +61,14 @@ EOF
) | /usr/sbin/sendmail -t ) | /usr/sbin/sendmail -t
#++ #++
# internals@ mail # commits@ mail
#-- #--
echo "Notifying internals list at $INTERNALS" echo "Notifying commits list at $COMMITS"
( (
cat <<EOF cat <<EOF
List-ID: <bk.mysql-$VERSION> List-ID: <bk.mysql-$VERSION>
From: $FROM From: $FROM
To: $INTERNALS To: $COMMITS
Subject: bk commit into $VERSION tree ($CHANGESET)$BS Subject: bk commit into $VERSION tree ($CHANGESET)$BS
X-CSetKey: <$CSETKEY> X-CSetKey: <$CSETKEY>
$BH $BH

View file

@ -120,6 +120,28 @@
<Filter <Filter
Name="Source Files" Name="Source Files"
Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"> Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
<File
RelativePath="crypto\aes_method.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\btree\bt_compact.c">
</File>
<File <File
RelativePath="btree\bt_compare.c"> RelativePath="btree\bt_compare.c">
<FileConfiguration <FileConfiguration
@ -500,6 +522,25 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="crypto\crypto.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="db\db.c"> RelativePath="db\db.c">
<FileConfiguration <FileConfiguration
@ -595,6 +636,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\common\db_clock.c">
</File>
<File <File
RelativePath="db\db_conv.c"> RelativePath="db\db_conv.c">
<FileConfiguration <FileConfiguration
@ -994,25 +1038,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="env\db_shash.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="db\db_setid.c"> RelativePath="db\db_setid.c">
<FileConfiguration <FileConfiguration
@ -1051,6 +1076,25 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="env\db_shash.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="db\db_stati.c"> RelativePath="db\db_stati.c">
<FileConfiguration <FileConfiguration
@ -1279,6 +1323,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\env\env_failchk.c">
</File>
<File <File
RelativePath="env\env_file.c"> RelativePath="env\env_file.c">
<FileConfiguration <FileConfiguration
@ -1374,6 +1421,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\env\env_register.c">
</File>
<File <File
RelativePath="env\env_stat.c"> RelativePath="env\env_stat.c">
<FileConfiguration <FileConfiguration
@ -1811,6 +1861,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\lock\lock_failchk.c">
</File>
<File <File
RelativePath="lock\lock_id.c"> RelativePath="lock\lock_id.c">
<FileConfiguration <FileConfiguration
@ -1831,7 +1884,7 @@
</FileConfiguration> </FileConfiguration>
</File> </File>
<File <File
RelativePath="lock\lock_method.c"> RelativePath="lock\lock_list.c">
<FileConfiguration <FileConfiguration
Name="Max|Win32"> Name="Max|Win32">
<Tool <Tool
@ -1850,7 +1903,7 @@
</FileConfiguration> </FileConfiguration>
</File> </File>
<File <File
RelativePath="lock\lock_list.c"> RelativePath="lock\lock_method.c">
<FileConfiguration <FileConfiguration
Name="Max|Win32"> Name="Max|Win32">
<Tool <Tool
@ -2001,6 +2054,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\log\log_debug.c">
</File>
<File <File
RelativePath="log\log_get.c"> RelativePath="log\log_get.c">
<FileConfiguration <FileConfiguration
@ -2324,6 +2380,37 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="crypto\mersenne\mt19937db.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath=".\mutex\mut_alloc.c">
</File>
<File
RelativePath=".\mutex\mut_method.c">
</File>
<File
RelativePath=".\mutex\mut_region.c">
</File>
<File
RelativePath=".\mutex\mut_stat.c">
</File>
<File <File
RelativePath="mutex\mut_tas.c"> RelativePath="mutex\mut_tas.c">
<FileConfiguration <FileConfiguration
@ -2362,25 +2449,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="mutex\mutex.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="os_win32\os_abs.c"> RelativePath="os_win32\os_abs.c">
<FileConfiguration <FileConfiguration
@ -2514,6 +2582,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\os_win32\os_flock.c">
</File>
<File <File
RelativePath="os_win32\os_fsync.c"> RelativePath="os_win32\os_fsync.c">
<FileConfiguration <FileConfiguration
@ -3103,6 +3174,12 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\rep\rep_elect.c">
</File>
<File
RelativePath=".\rep\rep_log.c">
</File>
<File <File
RelativePath="rep\rep_method.c"> RelativePath="rep\rep_method.c">
<FileConfiguration <FileConfiguration
@ -3179,6 +3256,9 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\rep\rep_stub.c">
</File>
<File <File
RelativePath="rep\rep_util.c"> RelativePath="rep\rep_util.c">
<FileConfiguration <FileConfiguration
@ -3198,6 +3278,47 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\rep\rep_verify.c">
</File>
<File
RelativePath="crypto\rijndael\rijndael-alg-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\rijndael\rijndael-api-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="hmac\sha1.c"> RelativePath="hmac\sha1.c">
<FileConfiguration <FileConfiguration
@ -3274,6 +3395,12 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath=".\txn\txn_chkpt.c">
</File>
<File
RelativePath=".\txn\txn_failchk.c">
</File>
<File <File
RelativePath="txn\txn_method.c"> RelativePath="txn\txn_method.c">
<FileConfiguration <FileConfiguration
@ -3483,101 +3610,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="crypto\aes_method.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\crypto.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\mersenne\mt19937db.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\rijndael\rijndael-api-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File
RelativePath="crypto\rijndael\rijndael-alg-fst.c">
<FileConfiguration
Name="Max|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"

View file

@ -341,6 +341,7 @@ long SSL_CTX_sess_set_cache_size(SSL_CTX*, long);
long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*); long SSL_CTX_set_tmp_dh(SSL_CTX*, DH*);
void OpenSSL_add_all_algorithms(void); void OpenSSL_add_all_algorithms(void);
void SSL_library_init();
void SSLeay_add_ssl_algorithms(void); void SSLeay_add_ssl_algorithms(void);

View file

@ -648,6 +648,10 @@ void OpenSSL_add_all_algorithms() // compatibility only
{} {}
void SSL_library_init() // compatibility only
{}
DH* DH_new(void) DH* DH_new(void)
{ {
DH* dh = new (ys) DH; DH* dh = new (ys) DH;

View file

@ -117,6 +117,9 @@ typedef unsigned long long my_ulonglong;
#define MYSQL_COUNT_ERROR (~(my_ulonglong) 0) #define MYSQL_COUNT_ERROR (~(my_ulonglong) 0)
/* backward compatibility define - to be removed eventually */
#define ER_WARN_DATA_TRUNCATED WARN_DATA_TRUNCATED
typedef struct st_mysql_rows { typedef struct st_mysql_rows {
struct st_mysql_rows *next; /* list of rows */ struct st_mysql_rows *next; /* list of rows */
MYSQL_ROW data; MYSQL_ROW data;

View file

@ -0,0 +1,122 @@
delimiter |;
---------------------------------------------------------------------------
CREATE PROCEDURE sp_vars_check_dflt()
BEGIN
DECLARE v1 TINYINT DEFAULT 1e200;
DECLARE v1u TINYINT UNSIGNED DEFAULT 1e200;
DECLARE v2 TINYINT DEFAULT -1e200;
DECLARE v2u TINYINT UNSIGNED DEFAULT -1e200;
DECLARE v3 TINYINT DEFAULT 300;
DECLARE v3u TINYINT UNSIGNED DEFAULT 300;
DECLARE v4 TINYINT DEFAULT -300;
DECLARE v4u TINYINT UNSIGNED DEFAULT -300;
DECLARE v5 TINYINT DEFAULT 10 * 10 * 10;
DECLARE v5u TINYINT UNSIGNED DEFAULT 10 * 10 * 10;
DECLARE v6 TINYINT DEFAULT -10 * 10 * 10;
DECLARE v6u TINYINT UNSIGNED DEFAULT -10 * 10 * 10;
DECLARE v7 TINYINT DEFAULT '10';
DECLARE v8 TINYINT DEFAULT '10 ';
DECLARE v9 TINYINT DEFAULT ' 10 ';
DECLARE v10 TINYINT DEFAULT 'String 10 ';
DECLARE v11 TINYINT DEFAULT 'String10';
DECLARE v12 TINYINT DEFAULT '10 String';
DECLARE v13 TINYINT DEFAULT '10String';
DECLARE v14 TINYINT DEFAULT concat('10', ' ');
DECLARE v15 TINYINT DEFAULT concat(' ', '10');
DECLARE v16 TINYINT DEFAULT concat('Hello, ', 'world');
DECLARE v17 DECIMAL(64, 2) DEFAULT 12;
DECLARE v18 DECIMAL(64, 2) DEFAULT 12.123;
DECLARE v19 DECIMAL(64, 2) DEFAULT 11 + 1;
DECLARE v20 DECIMAL(64, 2) DEFAULT 12 + 0.123;
SELECT v1, v1u, v2, v2u, v3, v3u, v4, v4u;
SELECT v5, v5u, v6, v6u;
SELECT v7, v8, v9, v10, v11, v12, v13, v14, v15, v16;
SELECT v17, v18, v19, v20;
END|
---------------------------------------------------------------------------
CREATE PROCEDURE sp_vars_check_assignment()
BEGIN
DECLARE i1, i2, i3, i4 TINYINT;
DECLARE u1, u2, u3, u4 TINYINT UNSIGNED;
DECLARE d1, d2, d3 DECIMAL(64, 2);
SET i1 = 1e200;
SET i2 = -1e200;
SET i3 = 300;
SET i4 = -300;
SELECT i1, i2, i3, i4;
SET i1 = 10 * 10 * 10;
SET i2 = -10 * 10 * 10;
SET i3 = sign(10 * 10) * 10 * 20;
SET i4 = sign(-10 * 10) * -10 * 20;
SELECT i1, i2, i3, i4;
SET u1 = 1e200;
SET u2 = -1e200;
SET u3 = 300;
SET u4 = -300;
SELECT u1, u2, u3, u4;
SET u1 = 10 * 10 * 10;
SET u2 = -10 * 10 * 10;
SET u3 = sign(10 * 10) * 10 * 20;
SET u4 = sign(-10 * 10) * -10 * 20;
SELECT u1, u2, u3, u4;
SET d1 = 1234;
SET d2 = 1234.12;
SET d3 = 1234.1234;
SELECT d1, d2, d3;
SET d1 = 12 * 100 + 34;
SET d2 = 12 * 100 + 34 + 0.12;
SET d3 = 12 * 100 + 34 + 0.1234;
SELECT d1, d2, d3;
END|
---------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret1() RETURNS TINYINT
BEGIN
RETURN 1e200;
END|
---------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret2() RETURNS TINYINT
BEGIN
RETURN 10 * 10 * 10;
END|
---------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret3() RETURNS TINYINT
BEGIN
RETURN 'Hello, world';
END|
---------------------------------------------------------------------------
CREATE FUNCTION sp_vars_check_ret4() RETURNS DECIMAL(64, 2)
BEGIN
RETURN 12 * 10 + 34 + 0.1234;
END|
---------------------------------------------------------------------------
delimiter ;|

View file

@ -2317,7 +2317,7 @@ CREATE TABLE t2(c2 char(2)) default charset = ujis;
INSERT INTO t1 VALUES(_ujis 0xA4A2); INSERT INTO t1 VALUES(_ujis 0xA4A2);
CREATE PROCEDURE sp1() CREATE PROCEDURE sp1()
BEGIN BEGIN
DECLARE a CHAR(1); DECLARE a CHAR(2) CHARSET ujis;
DECLARE cur1 CURSOR FOR SELECT c1 FROM t1; DECLARE cur1 CURSOR FOR SELECT c1 FROM t1;
OPEN cur1; OPEN cur1;
FETCH cur1 INTO a; FETCH cur1 INTO a;

View file

@ -1,3 +1,4 @@
drop database if exists mysqltest1;
create schema foo; create schema foo;
show create schema foo; show create schema foo;
Database Create Database Database Create Database

View file

@ -1,6 +1,7 @@
drop table if exists t1,t2; drop table if exists t1,t2;
drop table if exists t1aa,t2aa; drop table if exists t1aa,t2aa;
drop database if exists mysqltest; drop database if exists mysqltest;
drop database if exists mysqltest1;
delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
flush privileges; flush privileges;

View file

@ -10,5 +10,5 @@ user()
# #
show processlist; show processlist;
Id User Host db Command Time State Info Id User Host db Command Time State Info
# root # test Sleep # NULL <id> root <host> test <command> <time> <state> <info>
# root # test Query # NULL show processlist <id> root <host> test <command> <time> <state> <info>

View file

@ -25,6 +25,7 @@ count(*)
select count(*) from t2; select count(*) from t2;
count(*) count(*)
0 0
drop procedure if exists p1;
create procedure p1() create procedure p1()
begin begin
declare done integer default 0; declare done integer default 0;

View file

@ -0,0 +1,77 @@
use test;
drop procedure if exists bug14233;
drop function if exists bug14233;
drop table if exists t1;
drop view if exists v1;
create procedure bug14233()
set @x = 42;
create function bug14233_f() returns int
return 42;
create table t1 (id int);
create trigger t1_ai after insert on t1 for each row call bug14233();
alter table mysql.proc drop type;
call bug14233();
ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5)
create view v1 as select bug14233_f();
ERROR HY000: Failed to load routine test.bug14233_f. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5)
insert into t1 values (0);
ERROR HY000: Failed to load routine test.bug14233. The table mysql.proc is missing, corrupt, or contains bad data (internal code -5)
flush table mysql.proc;
call bug14233();
ERROR HY000: Incorrect information in file: './mysql/proc.frm'
create view v1 as select bug14233_f();
ERROR HY000: Incorrect information in file: './mysql/proc.frm'
insert into t1 values (0);
ERROR HY000: Incorrect information in file: './mysql/proc.frm'
flush table mysql.proc;
call bug14233();
ERROR 42S02: Table 'mysql.proc' doesn't exist
create view v1 as select bug14233_f();
ERROR 42S02: Table 'mysql.proc' doesn't exist
insert into t1 values (0);
ERROR 42S02: Table 'mysql.proc' doesn't exist
flush table mysql.proc;
flush privileges;
delete from mysql.proc where name like 'bug14233%';
insert into mysql.proc
(
db, name, type, specific_name, language, sql_data_access, is_deterministic,
security_type, param_list, returns, body, definer, created, modified,
sql_mode, comment
)
values
(
'test', 'bug14233_1', 'FUNCTION', 'bug14233_1', 'SQL', 'READS_SQL_DATA', 'NO',
'DEFINER', '', 'int(10)',
'select count(*) from mysql.user',
'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
),
(
'test', 'bug14233_2', 'FUNCTION', 'bug14233_2', 'SQL', 'READS_SQL_DATA', 'NO',
'DEFINER', '', 'int(10)',
'begin declare x int; select count(*) into x from mysql.user; end',
'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
),
(
'test', 'bug14233_3', 'PROCEDURE', 'bug14233_3', 'SQL', 'READS_SQL_DATA','NO',
'DEFINER', '', '',
'alksj wpsj sa ^#!@ ',
'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
);
select bug14233_1();
ERROR HY000: Failed to load routine test.bug14233_1. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
create view v1 as select bug14233_1();
ERROR HY000: Failed to load routine test.bug14233_1. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
select bug14233_2();
ERROR HY000: Failed to load routine test.bug14233_2. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
create view v1 as select bug14233_2();
ERROR HY000: Failed to load routine test.bug14233_2. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
call bug14233_3();
ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
drop trigger t1_ai;
create trigger t1_ai after insert on t1 for each row call bug14233_3();
insert into t1 values (0);
ERROR HY000: Failed to load routine test.bug14233_3. The table mysql.proc is missing, corrupt, or contains bad data (internal code -6)
delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai;
drop table t1;

View file

@ -1,3 +1,5 @@
drop procedure if exists p1|
drop procedure if exists p2|
create procedure p1() create procedure p1()
begin begin
prepare stmt from "select 1"; prepare stmt from "select 1";

View file

@ -124,7 +124,7 @@ begin
declare x int; declare x int;
set x = val+3; set x = val+3;
end| end|
ERROR 42000: No RETURN found in FUNCTION f ERROR 42000: No RETURN found in FUNCTION test.f
create function f(val int) returns int create function f(val int) returns int
begin begin
declare x int; declare x int;
@ -768,7 +768,7 @@ BEGIN
OPTIMIZE TABLE t1; OPTIMIZE TABLE t1;
RETURN 1; RETURN 1;
END| END|
ERROR 0A000: OPTIMIZE TABLE is not allowed in stored procedures ERROR 0A000: Not allowed to return a result set from a function
DROP FUNCTION IF EXISTS bug12995| DROP FUNCTION IF EXISTS bug12995|
CREATE FUNCTION bug12995() RETURNS INT CREATE FUNCTION bug12995() RETURNS INT
BEGIN BEGIN
@ -981,6 +981,8 @@ END |
drop table t1| drop table t1|
drop function bug_13627_f| drop function bug_13627_f|
drop function if exists bug12329; drop function if exists bug12329;
Warnings:
Note 1305 FUNCTION bug12329 does not exist
create table t1 as select 1 a; create table t1 as select 1 a;
create table t2 as select 1 a; create table t2 as select 1 a;
create function bug12329() returns int return (select a from t1); create function bug12329() returns int return (select a from t1);
@ -1055,3 +1057,34 @@ Db Name Type Definer Modified Created Security_type Comment
mysqltest2 p1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER mysqltest2 p1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
drop database mysqltest2; drop database mysqltest2;
use test; use test;
DROP FUNCTION IF EXISTS bug13012|
CREATE FUNCTION bug13012() RETURNS INT
BEGIN
REPAIR TABLE t1;
RETURN 1;
END|
ERROR 0A000: Not allowed to return a result set from a function
CREATE FUNCTION bug13012() RETURNS INT
BEGIN
BACKUP TABLE t1 TO '/tmp';
RETURN 1;
END|
ERROR 0A000: Not allowed to return a result set from a function
CREATE FUNCTION bug13012() RETURNS INT
BEGIN
RESTORE TABLE t1 FROM '/tmp';
RETURN 1;
END|
ERROR 0A000: Not allowed to return a result set from a function
create table t1 (a int)|
CREATE PROCEDURE bug13012_1() REPAIR TABLE t1|
CREATE FUNCTION bug13012_2() RETURNS INT
BEGIN
CALL bug13012_1();
RETURN 1;
END|
SELECT bug13012_2()|
ERROR 0A000: Not allowed to return a result set from a function
drop table t1|
drop procedure bug13012_1|
drop function bug13012_2|

1077
mysql-test/r/sp-vars.result Normal file

File diff suppressed because it is too large Load diff

View file

@ -248,13 +248,13 @@ return i+1|
call sub1("sub1a", (select 7))| call sub1("sub1a", (select 7))|
call sub1("sub1b", (select max(i) from t2))| call sub1("sub1b", (select max(i) from t2))|
call sub1("sub1c", (select i,d from t2 limit 1))| call sub1("sub1c", (select i,d from t2 limit 1))|
ERROR 21000: Operand should contain 1 column(s)
call sub1("sub1d", (select 1 from (select 1) a))| call sub1("sub1d", (select 1 from (select 1) a))|
call sub2("sub2")| call sub2("sub2")|
select * from t1| select * from t1|
id data id data
sub1a 7 sub1a 7
sub1b 3 sub1b 3
sub1c 1
sub1d 1 sub1d 1
sub2 6 sub2 6
select sub3((select max(i) from t2))| select sub3((select max(i) from t2))|
@ -2686,7 +2686,7 @@ call bug8937()|
s x y z s x y z
16 3 1 6 16 3 1 6
a a
3.2000 3.2
drop procedure bug8937| drop procedure bug8937|
delete from t1| delete from t1|
drop procedure if exists bug6900| drop procedure if exists bug6900|
@ -2890,21 +2890,30 @@ create function bug9775(v1 char(1)) returns enum('a','b') return v1|
select bug9775('a'),bug9775('b'),bug9775('c')| select bug9775('a'),bug9775('b'),bug9775('c')|
bug9775('a') bug9775('b') bug9775('c') bug9775('a') bug9775('b') bug9775('c')
a b a b
Warnings:
Warning 1265 Data truncated for column 'bug9775('c')' at row 1
drop function bug9775| drop function bug9775|
create function bug9775(v1 int) returns enum('a','b') return v1| create function bug9775(v1 int) returns enum('a','b') return v1|
select bug9775(1),bug9775(2),bug9775(3)| select bug9775(1),bug9775(2),bug9775(3)|
bug9775(1) bug9775(2) bug9775(3) bug9775(1) bug9775(2) bug9775(3)
a b a b
Warnings:
Warning 1265 Data truncated for column 'bug9775(3)' at row 1
drop function bug9775| drop function bug9775|
create function bug9775(v1 char(1)) returns set('a','b') return v1| create function bug9775(v1 char(1)) returns set('a','b') return v1|
select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')| select bug9775('a'),bug9775('b'),bug9775('a,b'),bug9775('c')|
bug9775('a') bug9775('b') bug9775('a,b') bug9775('c') bug9775('a') bug9775('b') bug9775('a,b') bug9775('c')
a b a,b a b a
Warnings:
Warning 1265 Data truncated for column 'v1' at row 1
Warning 1265 Data truncated for column 'bug9775('c')' at row 1
drop function bug9775| drop function bug9775|
create function bug9775(v1 int) returns set('a','b') return v1| create function bug9775(v1 int) returns set('a','b') return v1|
select bug9775(1),bug9775(2),bug9775(3),bug9775(4)| select bug9775(1),bug9775(2),bug9775(3),bug9775(4)|
bug9775(1) bug9775(2) bug9775(3) bug9775(4) bug9775(1) bug9775(2) bug9775(3) bug9775(4)
a b a,b a b a,b
Warnings:
Warning 1265 Data truncated for column 'bug9775(4)' at row 1
drop function bug9775| drop function bug9775|
drop function if exists bug8861| drop function if exists bug8861|
create function bug8861(v1 int) returns year return v1| create function bug8861(v1 int) returns year return v1|
@ -2927,12 +2936,10 @@ create procedure bug9004_2(x char(16))
call bug9004_1(x)| call bug9004_1(x)|
call bug9004_1('12345678901234567')| call bug9004_1('12345678901234567')|
Warnings: Warnings:
Warning 1265 Data truncated for column 'id' at row 1 Warning 1265 Data truncated for column 'x' at row 1
Warning 1265 Data truncated for column 'id' at row 2
call bug9004_2('12345678901234567890')| call bug9004_2('12345678901234567890')|
Warnings: Warnings:
Warning 1265 Data truncated for column 'id' at row 1 Warning 1265 Data truncated for column 'x' at row 1
Warning 1265 Data truncated for column 'id' at row 2
delete from t1| delete from t1|
drop procedure bug9004_1| drop procedure bug9004_1|
drop procedure bug9004_2| drop procedure bug9004_2|
@ -3527,14 +3534,15 @@ end|
call bug12589_1()| call bug12589_1()|
Table Create Table Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` ( tm1 CREATE TEMPORARY TABLE `tm1` (
`spv1` decimal(1,0) unsigned default NULL `spv1` decimal(3,3) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings: Warnings:
Warning 1292 Truncated incorrect DECIMAL value: 'test' Warning 1264 Out of range value for column 'spv1' at row 1
Warning 1366 Incorrect decimal value: 'test' for column 'spv1' at row 1
call bug12589_2()| call bug12589_2()|
Table Create Table Table Create Table
tm1 CREATE TEMPORARY TABLE `tm1` ( tm1 CREATE TEMPORARY TABLE `tm1` (
`spv1` decimal(6,3) unsigned default NULL `spv1` decimal(6,3) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
call bug12589_3()| call bug12589_3()|
Table Create Table Table Create Table
@ -4016,34 +4024,37 @@ create procedure bug14643_1()
begin begin
declare continue handler for sqlexception select 'boo' as 'Handler'; declare continue handler for sqlexception select 'boo' as 'Handler';
begin begin
declare v int default x; declare v int default undefined_var;
if v = 1 then if v = 1 then
select 1; select 1;
else else
select 2; select v, isnull(v);
end if; end if;
end; end;
end| end|
create procedure bug14643_2() create procedure bug14643_2()
begin begin
declare continue handler for sqlexception select 'boo' as 'Handler'; declare continue handler for sqlexception select 'boo' as 'Handler';
case x case undefined_var
when 1 then when 1 then
select 1; select 1;
else else
select 2; select 2;
end case; end case;
select undefined_var;
end| end|
call bug14643_1()| call bug14643_1()|
Handler Handler
boo boo
2 v isnull(v)
2 NULL 1
call bug14643_2()| call bug14643_2()|
Handler Handler
boo boo
2 2
2 2
Handler
boo
drop procedure bug14643_1| drop procedure bug14643_1|
drop procedure bug14643_2| drop procedure bug14643_2|
drop procedure if exists bug14304| drop procedure if exists bug14304|
@ -4100,8 +4111,6 @@ x
4711 4711
drop procedure bug14376| drop procedure bug14376|
drop procedure if exists p1| drop procedure if exists p1|
Warnings:
Note 1305 PROCEDURE p1 does not exist
drop table if exists t1| drop table if exists t1|
create table t1 (a varchar(255))| create table t1 (a varchar(255))|
insert into t1 (a) values ("a - table column")| insert into t1 (a) values ("a - table column")|
@ -4153,4 +4162,141 @@ A local variable in a nested compound statement takes precedence over table colu
a - local variable in a nested compound statement a - local variable in a nested compound statement
A local variable in a nested compound statement takes precedence over table column in cursors A local variable in a nested compound statement takes precedence over table column in cursors
a - local variable in a nested compound statement a - local variable in a nested compound statement
drop procedure p1|
drop procedure if exists bug13012|
create procedure bug13012()
BEGIN
REPAIR TABLE t1;
BACKUP TABLE t1 to '../tmp';
DROP TABLE t1;
RESTORE TABLE t1 FROM '../tmp';
END|
call bug13012()|
Table Op Msg_type Msg_text
test.t1 repair status OK
Table Op Msg_type Msg_text
test.t1 backup status OK
Table Op Msg_type Msg_text
test.t1 restore status OK
drop procedure bug13012|
create view v1 as select * from t1|
create procedure bug13012()
BEGIN
REPAIR TABLE t1,t2,t3,v1;
OPTIMIZE TABLE t1,t2,t3,v1;
ANALYZE TABLE t1,t2,t3,v1;
END|
call bug13012()|
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair error Table 'test.t3' doesn't exist
test.v1 repair error 'test.v1' is not BASE TABLE
Table Op Msg_type Msg_text
test.t1 optimize status OK
test.t2 optimize status OK
test.t3 optimize error Table 'test.t3' doesn't exist
test.v1 optimize error 'test.v1' is not BASE TABLE
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
test.t2 analyze status Table is already up to date
test.t3 analyze error Table 'test.t3' doesn't exist
test.v1 analyze error 'test.v1' is not BASE TABLE
Warnings:
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
call bug13012()|
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair error Table 'test.t3' doesn't exist
test.v1 repair error 'test.v1' is not BASE TABLE
Table Op Msg_type Msg_text
test.t1 optimize status OK
test.t2 optimize status OK
test.t3 optimize error Table 'test.t3' doesn't exist
test.v1 optimize error 'test.v1' is not BASE TABLE
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
test.t2 analyze status Table is already up to date
test.t3 analyze error Table 'test.t3' doesn't exist
test.v1 analyze error 'test.v1' is not BASE TABLE
Warnings:
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
call bug13012()|
Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair error Table 'test.t3' doesn't exist
test.v1 repair error 'test.v1' is not BASE TABLE
Table Op Msg_type Msg_text
test.t1 optimize status OK
test.t2 optimize status OK
test.t3 optimize error Table 'test.t3' doesn't exist
test.v1 optimize error 'test.v1' is not BASE TABLE
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
test.t2 analyze status Table is already up to date
test.t3 analyze error Table 'test.t3' doesn't exist
test.v1 analyze error 'test.v1' is not BASE TABLE
Warnings:
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
Error 1146 Table 'test.t3' doesn't exist
Error 1347 'test.v1' is not BASE TABLE
drop procedure bug13012|
drop view v1;
select * from t1|
a
a - table column
drop schema if exists mysqltest1|
Warnings:
Note 1008 Can't drop database 'mysqltest1'; database doesn't exist
drop schema if exists mysqltest2|
Warnings:
Note 1008 Can't drop database 'mysqltest2'; database doesn't exist
drop schema if exists mysqltest3|
Warnings:
Note 1008 Can't drop database 'mysqltest3'; database doesn't exist
create schema mysqltest1|
create schema mysqltest2|
create schema mysqltest3|
use mysqltest3|
create procedure mysqltest1.p1 (out prequestid varchar(100))
begin
call mysqltest2.p2('call mysqltest3.p3(1, 2)');
end|
create procedure mysqltest2.p2(in psql text)
begin
declare lsql text;
set @lsql= psql;
prepare lstatement from @lsql;
execute lstatement;
deallocate prepare lstatement;
end|
create procedure mysqltest3.p3(in p1 int)
begin
select p1;
end|
call mysqltest1.p1(@rs)|
ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
call mysqltest1.p1(@rs)|
ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
call mysqltest1.p1(@rs)|
ERROR 42000: Incorrect number of arguments for PROCEDURE mysqltest3.p3; expected 1, got 2
drop schema if exists mysqltest1|
drop schema if exists mysqltest2|
drop schema if exists mysqltest3|
use test|
drop table t1,t2; drop table t1,t2;

View file

@ -1,5 +1,4 @@
using_big_test DROP TABLE IF EXISTS t1, t2;
0
CREATE TABLE t1 (id INTEGER); CREATE TABLE t1 (id INTEGER);
CREATE TABLE t2 (id INTEGER); CREATE TABLE t2 (id INTEGER);
INSERT INTO t1 (id) VALUES (1), (1), (1),(1); INSERT INTO t1 (id) VALUES (1), (1), (1),(1);
@ -40,19 +39,19 @@ AVG(DISTINCT id)
512.5000 512.5000
SELECT SUM(DISTINCT id)/COUNT(DISTINCT id) FROM t1 GROUP BY id % 13; SELECT SUM(DISTINCT id)/COUNT(DISTINCT id) FROM t1 GROUP BY id % 13;
SUM(DISTINCT id)/COUNT(DISTINCT id) SUM(DISTINCT id)/COUNT(DISTINCT id)
513.50000 513.5000
508.00000 508.0000
509.00000 509.0000
510.00000 510.0000
511.00000 511.0000
512.00000 512.0000
513.00000 513.0000
514.00000 514.0000
515.00000 515.0000
516.00000 516.0000
517.00000 517.0000
511.50000 511.5000
512.50000 512.5000
INSERT INTO t1 SELECT id+1024 FROM t1; INSERT INTO t1 SELECT id+1024 FROM t1;
INSERT INTO t1 SELECT id+2048 FROM t1; INSERT INTO t1 SELECT id+2048 FROM t1;
INSERT INTO t1 SELECT id+4096 FROM t1; INSERT INTO t1 SELECT id+4096 FROM t1;

View file

@ -114,3 +114,26 @@ drop table t1;
select hex(cast(0x10 as binary(2))); select hex(cast(0x10 as binary(2)));
hex(cast(0x10 as binary(2))) hex(cast(0x10 as binary(2)))
1000 1000
create table t1 (b binary(2), vb varbinary(2));
insert into t1 values(0x4120, 0x4120);
insert into t1 values(0x412020, 0x412020);
Warnings:
Warning 1265 Data truncated for column 'b' at row 1
Warning 1265 Data truncated for column 'vb' at row 1
drop table t1;
create table t1 (c char(2), vc varchar(2));
insert into t1 values(0x4120, 0x4120);
insert into t1 values(0x412020, 0x412020);
Warnings:
Note 1265 Data truncated for column 'vc' at row 1
drop table t1;
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
create table t1 (b binary(2), vb varbinary(2));
insert into t1 values(0x4120, 0x4120);
insert into t1 values(0x412020, NULL);
ERROR 22001: Data too long for column 'b' at row 1
insert into t1 values(NULL, 0x412020);
ERROR 22001: Data too long for column 'vb' at row 1
drop table t1;
set @@sql_mode= @old_sql_mode;
End of 5.0 tests

View file

@ -1,11 +1,26 @@
drop procedure if exists sp1; drop procedure if exists sp1;
create procedure sp1 () begin CREATE PROCEDURE sp1()
declare v1, v2, v3, v4 decimal(16,12); declare v5 int; BEGIN
set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; DECLARE v1, v2, v3, v4 DECIMAL(28,12);
while v5 < 100000 do DECLARE v3_2, v4_2 DECIMAL(28, 12);
set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; DECLARE counter INT;
end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// SET v1 = 1;
SET v2 = 2;
SET v3 = 1000000000000;
SET v4 = 2000000000000;
SET counter = 0;
WHILE counter < 100000 DO
SET v1 = v1 + 0.000000000001;
SET v2 = v2 - 0.000000000001;
SET v3 = v3 + 1;
SET v4 = v4 - 1;
SET counter = counter + 1;
END WHILE;
SET v3_2 = v3 * 0.000000000001;
SET v4_2 = v4 * 0.000000000001;
SELECT v1, v2, v3, v3_2, v4, v4_2;
END//
call sp1()// call sp1()//
v1 v2 v3 * 0.000000000001 v4 * 0.000000000001 v1 v2 v3 v3_2 v4 v4_2
1.000000100000 1.999999900000 1.000000100000 1.999999900000 1.000000100000 1.999999900000 1000000100000.000000000000 1.000000100000 1999999900000.000000000000 1.999999900000
drop procedure sp1; drop procedure sp1;

View file

@ -2383,20 +2383,25 @@ CREATE TABLE t1(id INT);
CREATE VIEW v1 AS SELECT id FROM t1; CREATE VIEW v1 AS SELECT id FROM t1;
OPTIMIZE TABLE v1; OPTIMIZE TABLE v1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.v1 optimize note Unknown table 'test.v1' test.v1 optimize error 'test.v1' is not BASE TABLE
Warnings:
Error 1347 'test.v1' is not BASE TABLE
ANALYZE TABLE v1; ANALYZE TABLE v1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.v1 analyze note Unknown table 'test.v1' test.v1 analyze error 'test.v1' is not BASE TABLE
Warnings:
Error 1347 'test.v1' is not BASE TABLE
REPAIR TABLE v1; REPAIR TABLE v1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.v1 repair note Unknown table 'test.v1' test.v1 repair error 'test.v1' is not BASE TABLE
Warnings:
Error 1347 'test.v1' is not BASE TABLE
DROP TABLE t1; DROP TABLE t1;
OPTIMIZE TABLE v1; OPTIMIZE TABLE v1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.v1 optimize note Unknown table 'test.v1' test.v1 optimize error 'test.v1' is not BASE TABLE
Warnings: Warnings:
Error 1146 Table 'test.t1' doesn't exist Error 1347 'test.v1' is not BASE TABLE
Error 1356 View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
DROP VIEW v1; DROP VIEW v1;
create definer = current_user() sql security invoker view v1 as select 1; create definer = current_user() sql security invoker view v1 as select 1;
show create view v1; show create view v1;

View file

@ -52,5 +52,6 @@ unlock tables;
connection con1; connection con1;
reap; reap;
drop table t5; drop table t5;
--system rm $MYSQL_TEST_DIR/var/tmp/t?.*
# End of 4.1 tests # End of 4.1 tests

View file

@ -1170,7 +1170,7 @@ INSERT INTO t1 VALUES(_ujis 0xA4A2);
DELIMITER |; DELIMITER |;
CREATE PROCEDURE sp1() CREATE PROCEDURE sp1()
BEGIN BEGIN
DECLARE a CHAR(1); DECLARE a CHAR(2) CHARSET ujis;
DECLARE cur1 CURSOR FOR SELECT c1 FROM t1; DECLARE cur1 CURSOR FOR SELECT c1 FROM t1;
OPEN cur1; OPEN cur1;
FETCH cur1 INTO a; FETCH cur1 INTO a;

View file

@ -1,6 +1,12 @@
# #
# Just a couple of tests to make sure that schema works. # Just a couple of tests to make sure that schema works.
# #
# Drop mysqltest1 database, as it can left from the previous tests.
#
--disable_warnings
drop database if exists mysqltest1;
--enable_warnings
create schema foo; create schema foo;
show create schema foo; show create schema foo;

View file

@ -10,6 +10,7 @@
drop table if exists t1,t2; drop table if exists t1,t2;
drop table if exists t1aa,t2aa; drop table if exists t1aa,t2aa;
drop database if exists mysqltest; drop database if exists mysqltest;
drop database if exists mysqltest1;
delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.user where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';
delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3'; delete from mysql.db where user='mysqltest_1' || user='mysqltest_2' || user='mysqltest_3';

View file

@ -15,6 +15,6 @@ DROP USER mysqltest_1@'127.0.0.1/255.255.255.255';
connect (con1, 127.0.0.1, root, , test, $MASTER_MYPORT, ); connect (con1, 127.0.0.1, root, , test, $MASTER_MYPORT, );
--replace_column 1 # --replace_column 1 #
select user(); select user();
--replace_column 1 # 6 # 3 # --replace_column 1 <id> 3 <host> 5 <command> 6 <time> 7 <state> 8 <info>
show processlist; show processlist;
connection default; connection default;

View file

@ -52,6 +52,9 @@ while ($1)
--enable_query_log --enable_query_log
select count(*) from t1; select count(*) from t1;
select count(*) from t2; select count(*) from t2;
--disable_warnings
drop procedure if exists p1;
--enable_warnings
delimiter |; delimiter |;
create procedure p1() create procedure p1()
begin begin

View file

@ -0,0 +1,124 @@
#
# Destructive stored procedure tests
#
# We do horrible things to the mysql.proc table here, so any unexpected
# failures here might leave it in an undetermined state.
#
# In the case of trouble you might want to skip this.
#
# We're using --system things that probably doesn't work on Windows.
--source include/not_windows.inc
# Backup proc table
--system rm -rf var/master-data/mysql/backup
--system mkdir var/master-data/mysql/backup
--system cp var/master-data/mysql/proc.* var/master-data/mysql/backup/
use test;
--disable_warnings
drop procedure if exists bug14233;
drop function if exists bug14233;
drop table if exists t1;
drop view if exists v1;
--enable_warnings
create procedure bug14233()
set @x = 42;
create function bug14233_f() returns int
return 42;
create table t1 (id int);
create trigger t1_ai after insert on t1 for each row call bug14233();
# Unsupported tampering with the mysql.proc definition
alter table mysql.proc drop type;
--error ER_SP_PROC_TABLE_CORRUPT
call bug14233();
--error ER_SP_PROC_TABLE_CORRUPT
create view v1 as select bug14233_f();
--error ER_SP_PROC_TABLE_CORRUPT
insert into t1 values (0);
flush table mysql.proc;
# Thrashing the .frm file
--system echo 'saljdlfa' > var/master-data/mysql/proc.frm
--error ER_NOT_FORM_FILE
call bug14233();
--error ER_NOT_FORM_FILE
create view v1 as select bug14233_f();
--error ER_NOT_FORM_FILE
insert into t1 values (0);
flush table mysql.proc;
# Drop the mysql.proc table
--system rm var/master-data/mysql/proc.*
--error ER_NO_SUCH_TABLE
call bug14233();
--error ER_NO_SUCH_TABLE
create view v1 as select bug14233_f();
--error ER_NO_SUCH_TABLE
insert into t1 values (0);
# Restore mysql.proc
--system mv var/master-data/mysql/backup/* var/master-data/mysql/
--system rmdir var/master-data/mysql/backup
flush table mysql.proc;
flush privileges;
delete from mysql.proc where name like 'bug14233%';
# Unsupported editing of mysql.proc, circumventing checks in "create ..."
insert into mysql.proc
(
db, name, type, specific_name, language, sql_data_access, is_deterministic,
security_type, param_list, returns, body, definer, created, modified,
sql_mode, comment
)
values
(
'test', 'bug14233_1', 'FUNCTION', 'bug14233_1', 'SQL', 'READS_SQL_DATA', 'NO',
'DEFINER', '', 'int(10)',
'select count(*) from mysql.user',
'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
),
(
'test', 'bug14233_2', 'FUNCTION', 'bug14233_2', 'SQL', 'READS_SQL_DATA', 'NO',
'DEFINER', '', 'int(10)',
'begin declare x int; select count(*) into x from mysql.user; end',
'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
),
(
'test', 'bug14233_3', 'PROCEDURE', 'bug14233_3', 'SQL', 'READS_SQL_DATA','NO',
'DEFINER', '', '',
'alksj wpsj sa ^#!@ ',
'root@localhost', NOW() , '0000-00-00 00:00:00', '', ''
);
--error ER_SP_PROC_TABLE_CORRUPT
select bug14233_1();
--error ER_SP_PROC_TABLE_CORRUPT
create view v1 as select bug14233_1();
--error ER_SP_PROC_TABLE_CORRUPT
select bug14233_2();
--error ER_SP_PROC_TABLE_CORRUPT
create view v1 as select bug14233_2();
--error ER_SP_PROC_TABLE_CORRUPT
call bug14233_3();
drop trigger t1_ai;
create trigger t1_ai after insert on t1 for each row call bug14233_3();
--error ER_SP_PROC_TABLE_CORRUPT
insert into t1 values (0);
# Clean-up
delete from mysql.proc where name like 'bug14233%';
drop trigger t1_ai;
drop table t1;

View file

@ -1,4 +1,10 @@
delimiter |; delimiter |;
--disable_warnings
drop procedure if exists p1|
drop procedure if exists p2|
--enable_warnings
###################################################################### ######################################################################
# Test Dynamic SQL in stored procedures. ############################# # Test Dynamic SQL in stored procedures. #############################
###################################################################### ######################################################################

View file

@ -1095,7 +1095,7 @@ delimiter |;
--disable_warnings --disable_warnings
DROP FUNCTION IF EXISTS bug12953| DROP FUNCTION IF EXISTS bug12953|
--enable_warnings --enable_warnings
--error ER_SP_BADSTATEMENT --error ER_SP_NO_RETSET
CREATE FUNCTION bug12953() RETURNS INT CREATE FUNCTION bug12953() RETURNS INT
BEGIN BEGIN
OPTIMIZE TABLE t1; OPTIMIZE TABLE t1;
@ -1410,7 +1410,6 @@ delimiter ;|
# BUG#12329: "Bogus error msg when executing PS with stored procedure after # BUG#12329: "Bogus error msg when executing PS with stored procedure after
# SP was re-created". See also test for related bug#13399 in trigger.test # SP was re-created". See also test for related bug#13399 in trigger.test
--disable_warnings
drop function if exists bug12329; drop function if exists bug12329;
--enable_warnings --enable_warnings
create table t1 as select 1 a; create table t1 as select 1 a;
@ -1518,6 +1517,44 @@ show procedure status;
drop database mysqltest2; drop database mysqltest2;
use test; use test;
#
# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server"
#
delimiter |;
--disable_warnings
DROP FUNCTION IF EXISTS bug13012|
--enable_warnings
--error ER_SP_NO_RETSET
CREATE FUNCTION bug13012() RETURNS INT
BEGIN
REPAIR TABLE t1;
RETURN 1;
END|
--error ER_SP_NO_RETSET
CREATE FUNCTION bug13012() RETURNS INT
BEGIN
BACKUP TABLE t1 TO '/tmp';
RETURN 1;
END|
--error ER_SP_NO_RETSET
CREATE FUNCTION bug13012() RETURNS INT
BEGIN
RESTORE TABLE t1 FROM '/tmp';
RETURN 1;
END|
create table t1 (a int)|
CREATE PROCEDURE bug13012_1() REPAIR TABLE t1|
CREATE FUNCTION bug13012_2() RETURNS INT
BEGIN
CALL bug13012_1();
RETURN 1;
END|
--error ER_SP_NO_RETSET
SELECT bug13012_2()|
drop table t1|
drop procedure bug13012_1|
drop function bug13012_2|
delimiter ;|
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
# #

1273
mysql-test/t/sp-vars.test Normal file

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,8 @@
# Tests that require multiple connections, except security/privilege tests, # Tests that require multiple connections, except security/privilege tests,
# go to sp-thread. # go to sp-thread.
# Tests that uses 'goto' to into sp-goto.test (currently disabled) # Tests that uses 'goto' to into sp-goto.test (currently disabled)
# Tests that destroys system tables (e.g. mysql.proc) for error testing
# go to sp-destruct.
use test; use test;
@ -365,6 +367,7 @@ create function sub3(i int) returns int
call sub1("sub1a", (select 7))| call sub1("sub1a", (select 7))|
call sub1("sub1b", (select max(i) from t2))| call sub1("sub1b", (select max(i) from t2))|
--error ER_OPERAND_COLUMNS
call sub1("sub1c", (select i,d from t2 limit 1))| call sub1("sub1c", (select i,d from t2 limit 1))|
call sub1("sub1d", (select 1 from (select 1) a))| call sub1("sub1d", (select 1 from (select 1) a))|
call sub2("sub2")| call sub2("sub2")|
@ -4795,12 +4798,12 @@ begin
declare continue handler for sqlexception select 'boo' as 'Handler'; declare continue handler for sqlexception select 'boo' as 'Handler';
begin begin
declare v int default x; declare v int default undefined_var;
if v = 1 then if v = 1 then
select 1; select 1;
else else
select 2; select v, isnull(v);
end if; end if;
end; end;
end| end|
@ -4809,12 +4812,14 @@ create procedure bug14643_2()
begin begin
declare continue handler for sqlexception select 'boo' as 'Handler'; declare continue handler for sqlexception select 'boo' as 'Handler';
case x case undefined_var
when 1 then when 1 then
select 1; select 1;
else else
select 2; select 2;
end case; end case;
select undefined_var;
end| end|
call bug14643_1()| call bug14643_1()|
@ -4908,8 +4913,10 @@ drop procedure bug14376|
# variable declarations. In MySQL 5.0 it's vice versa. # variable declarations. In MySQL 5.0 it's vice versa.
# #
--disable_warnings
drop procedure if exists p1| drop procedure if exists p1|
drop table if exists t1| drop table if exists t1|
--enable_warnings
create table t1 (a varchar(255))| create table t1 (a varchar(255))|
insert into t1 (a) values ("a - table column")| insert into t1 (a) values ("a - table column")|
create procedure p1(a varchar(255)) create procedure p1(a varchar(255))
@ -4944,6 +4951,82 @@ begin
end; end;
end| end|
call p1("a - stored procedure parameter")| call p1("a - stored procedure parameter")|
drop procedure p1|
#
# Bug#13012 "SP: REPAIR/BACKUP/RESTORE TABLE crashes the server"
#
--disable_warnings
drop procedure if exists bug13012|
--enable_warnings
create procedure bug13012()
BEGIN
REPAIR TABLE t1;
BACKUP TABLE t1 to '../tmp';
DROP TABLE t1;
RESTORE TABLE t1 FROM '../tmp';
END|
call bug13012()|
drop procedure bug13012|
create view v1 as select * from t1|
create procedure bug13012()
BEGIN
REPAIR TABLE t1,t2,t3,v1;
OPTIMIZE TABLE t1,t2,t3,v1;
ANALYZE TABLE t1,t2,t3,v1;
END|
call bug13012()|
call bug13012()|
call bug13012()|
drop procedure bug13012|
drop view v1;
select * from t1|
#
# A test case for Bug#15392 "Server crashes during prepared statement
# execute": make sure that stored procedure check for error conditions
# properly and do not continue execution if an error has been set.
#
# It's necessary to use several DBs because in the original code
# the successful return of mysql_change_db overrode the error from
# execution.
drop schema if exists mysqltest1|
drop schema if exists mysqltest2|
drop schema if exists mysqltest3|
create schema mysqltest1|
create schema mysqltest2|
create schema mysqltest3|
use mysqltest3|
create procedure mysqltest1.p1 (out prequestid varchar(100))
begin
call mysqltest2.p2('call mysqltest3.p3(1, 2)');
end|
create procedure mysqltest2.p2(in psql text)
begin
declare lsql text;
set @lsql= psql;
prepare lstatement from @lsql;
execute lstatement;
deallocate prepare lstatement;
end|
create procedure mysqltest3.p3(in p1 int)
begin
select p1;
end|
--error ER_SP_WRONG_NO_OF_ARGS
call mysqltest1.p1(@rs)|
--error ER_SP_WRONG_NO_OF_ARGS
call mysqltest1.p1(@rs)|
--error ER_SP_WRONG_NO_OF_ARGS
call mysqltest1.p1(@rs)|
drop schema if exists mysqltest1|
drop schema if exists mysqltest2|
drop schema if exists mysqltest3|
use test|
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis

View file

@ -68,3 +68,27 @@ drop table t1;
# check that cast appends trailing zeros # check that cast appends trailing zeros
select hex(cast(0x10 as binary(2))); select hex(cast(0x10 as binary(2)));
#
# Bug #14299: BINARY space truncation should cause warning or error
#
create table t1 (b binary(2), vb varbinary(2));
insert into t1 values(0x4120, 0x4120);
insert into t1 values(0x412020, 0x412020);
drop table t1;
create table t1 (c char(2), vc varchar(2));
insert into t1 values(0x4120, 0x4120);
insert into t1 values(0x412020, 0x412020);
drop table t1;
set @old_sql_mode= @@sql_mode, sql_mode= 'traditional';
create table t1 (b binary(2), vb varbinary(2));
insert into t1 values(0x4120, 0x4120);
--error ER_DATA_TOO_LONG
insert into t1 values(0x412020, NULL);
--error ER_DATA_TOO_LONG
insert into t1 values(NULL, 0x412020);
drop table t1;
set @@sql_mode= @old_sql_mode;
--echo End of 5.0 tests

View file

@ -12,12 +12,31 @@ drop procedure if exists sp1;
delimiter //; delimiter //;
# #
create procedure sp1 () begin CREATE PROCEDURE sp1()
declare v1, v2, v3, v4 decimal(16,12); declare v5 int; BEGIN
set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; DECLARE v1, v2, v3, v4 DECIMAL(28,12);
while v5 < 100000 do DECLARE v3_2, v4_2 DECIMAL(28, 12);
set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; DECLARE counter INT;
end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;//
SET v1 = 1;
SET v2 = 2;
SET v3 = 1000000000000;
SET v4 = 2000000000000;
SET counter = 0;
WHILE counter < 100000 DO
SET v1 = v1 + 0.000000000001;
SET v2 = v2 - 0.000000000001;
SET v3 = v3 + 1;
SET v4 = v4 - 1;
SET counter = counter + 1;
END WHILE;
SET v3_2 = v3 * 0.000000000001;
SET v4_2 = v4 * 0.000000000001;
SELECT v1, v2, v3, v3_2, v4, v4_2;
END//
# #
call sp1()// call sp1()//
#-- should return #-- should return

View file

@ -5859,44 +5859,52 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
char buff[STRING_BUFFER_USUAL_SIZE]; char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin); String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length; uint copy_length;
/* See the comment for Field_long::store(long long) */ /* See the comment for Field_long::store(long long) */
DBUG_ASSERT(table->in_use == current_thd); DBUG_ASSERT(table->in_use == current_thd);
/* Convert character set if necessary */ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used)) if (String::needs_conversion(length, cs, field_charset, &not_used))
{ {
uint conv_errors; uint conv_errors;
tmpstr.copy(from, length, cs, field_charset, &conv_errors); tmpstr.copy(from, length, cs, field_charset, &conv_errors);
from= tmpstr.ptr(); from= tmpstr.ptr();
length= tmpstr.length(); length= tmpstr.length();
if (conv_errors) if (conv_errors)
error= 2; error= 2;
} }
/* /* Make sure we don't break a multibyte sequence or copy malformed data. */
Make sure we don't break a multibyte sequence
as well as don't copy a malformed data.
*/
copy_length= field_charset->cset->well_formed_len(field_charset, copy_length= field_charset->cset->well_formed_len(field_charset,
from,from+length, from,from+length,
field_length/ field_length/
field_charset->mbmaxlen, field_charset->mbmaxlen,
&well_formed_error); &well_formed_error);
memcpy(ptr,from,copy_length); memcpy(ptr,from,copy_length);
if (copy_length < field_length) // Append spaces if shorter
/* Append spaces if the string was shorter than the field. */
if (copy_length < field_length)
field_charset->cset->fill(field_charset,ptr+copy_length, field_charset->cset->fill(field_charset,ptr+copy_length,
field_length-copy_length, field_length-copy_length,
field_charset->pad_char); field_charset->pad_char);
/*
Check if we lost any important data (anything in a binary string,
or any non-space in others).
*/
if ((copy_length < length) && table->in_use->count_cuted_fields) if ((copy_length < length) && table->in_use->count_cuted_fields)
{ // Check if we loosed some info {
const char *end=from+length; if (binary())
from+= copy_length;
from+= field_charset->cset->scan(field_charset, from, end,
MY_SEQ_SPACES);
if (from != end)
error= 2; error= 2;
else
{
const char *end=from+length;
from+= copy_length;
from+= field_charset->cset->scan(field_charset, from, end,
MY_SEQ_SPACES);
if (from != end)
error= 2;
}
} }
if (error) if (error)
{ {
@ -6298,12 +6306,15 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
if ((copy_length < length) && table->in_use->count_cuted_fields && if ((copy_length < length) && table->in_use->count_cuted_fields &&
!error_code) !error_code)
{ {
const char *end= from + length; if (!binary())
from+= copy_length; {
from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES); const char *end= from + length;
/* If we lost only spaces then produce a NOTE, not a WARNING */ from+= copy_length;
if (from == end) from+= field_charset->cset->scan(field_charset, from, end, MY_SEQ_SPACES);
level= MYSQL_ERROR::WARN_LEVEL_NOTE; /* If we lost only spaces then produce a NOTE, not a WARNING */
if (from == end)
level= MYSQL_ERROR::WARN_LEVEL_NOTE;
}
error_code= WARN_DATA_TRUNCATED; error_code= WARN_DATA_TRUNCATED;
} }
if (error_code) if (error_code)
@ -6794,6 +6805,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
{ {
flags|= BLOB_FLAG; flags|= BLOB_FLAG;
share->blob_fields++; share->blob_fields++;
/* TODO: why do not fill table->s->blob_field array here? */
} }
@ -8358,6 +8370,350 @@ void create_field::init_for_tmp_table(enum_field_types sql_type_arg,
} }
/*
Initialize field definition for create
SYNOPSIS
thd Thread handle
fld_name Field name
fld_type Field type
fld_length Field length
fld_decimals Decimal (if any)
fld_type_modifier Additional type information
fld_default_value Field default value (if any)
fld_on_update_value The value of ON UPDATE clause
fld_comment Field comment
fld_change Field change
fld_interval_list Interval list (if any)
fld_charset Field charset
fld_geom_type Field geometry type (if any)
RETURN
FALSE on success
TRUE on error
*/
bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
char *fld_length, char *fld_decimals,
uint fld_type_modifier, Item *fld_default_value,
Item *fld_on_update_value, LEX_STRING *fld_comment,
char *fld_change, List<String> *fld_interval_list,
CHARSET_INFO *fld_charset, uint fld_geom_type)
{
uint sign_len, allowed_type_modifier= 0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("create_field::init()");
field= 0;
field_name= fld_name;
def= fld_default_value;
flags= fld_type_modifier;
unireg_check= (fld_type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
decimals= fld_decimals ? (uint)atoi(fld_decimals) : 0;
if (decimals >= NOT_FIXED_DEC)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
NOT_FIXED_DEC-1);
DBUG_RETURN(TRUE);
}
sql_type= fld_type;
length= 0;
change= fld_change;
interval= 0;
pack_length= key_length= 0;
charset= fld_charset;
geom_type= (Field::geometry_type) fld_geom_type;
interval_list.empty();
comment= *fld_comment;
/*
Set flag if this field doesn't have a default value
*/
if (!fld_default_value && !(fld_type_modifier & AUTO_INCREMENT_FLAG) &&
(fld_type_modifier & NOT_NULL_FLAG) && fld_type != FIELD_TYPE_TIMESTAMP)
flags|= NO_DEFAULT_VALUE_FLAG;
if (fld_length && !(length= (uint) atoi(fld_length)))
fld_length= 0; /* purecov: inspected */
sign_len= fld_type_modifier & UNSIGNED_FLAG ? 0 : 1;
switch (fld_type) {
case FIELD_TYPE_TINY:
if (!fld_length)
length= MAX_TINYINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_SHORT:
if (!fld_length)
length= MAX_SMALLINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_INT24:
if (!fld_length)
length= MAX_MEDIUMINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_LONG:
if (!fld_length)
length= MAX_INT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_LONGLONG:
if (!fld_length)
length= MAX_BIGINT_WIDTH;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_NULL:
break;
case FIELD_TYPE_NEWDECIMAL:
if (!fld_length && !decimals)
length= 10;
if (length > DECIMAL_MAX_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
DECIMAL_MAX_PRECISION);
DBUG_RETURN(TRUE);
}
if (length < decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
DBUG_RETURN(TRUE);
}
length=
my_decimal_precision_to_length(length, decimals,
fld_type_modifier & UNSIGNED_FLAG);
pack_length=
my_decimal_get_binary_size(length, decimals);
break;
case MYSQL_TYPE_VARCHAR:
/*
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
if they don't have a default value
*/
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
break;
case MYSQL_TYPE_STRING:
break;
case FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_GEOMETRY:
if (fld_default_value)
{
/* Allow empty as default value. */
String str,*res;
res= fld_default_value->val_str(&str);
if (res->length())
{
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
fld_name); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
def= 0;
}
flags|= BLOB_FLAG;
break;
case FIELD_TYPE_YEAR:
if (!fld_length || length != 2)
length= 4; /* Default length */
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
break;
case FIELD_TYPE_FLOAT:
/* change FLOAT(precision) to FLOAT or DOUBLE */
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (fld_length && !fld_decimals)
{
uint tmp_length= length;
if (tmp_length > PRECISION_FOR_DOUBLE)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
DBUG_RETURN(TRUE);
}
else if (tmp_length > PRECISION_FOR_FLOAT)
{
sql_type= FIELD_TYPE_DOUBLE;
length= DBL_DIG+7; /* -[digits].E+### */
}
else
length= FLT_DIG+6; /* -[digits].E+## */
decimals= NOT_FIXED_DEC;
break;
}
if (!fld_length && !fld_decimals)
{
length= FLT_DIG+6;
decimals= NOT_FIXED_DEC;
}
if (length < decimals &&
decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
DBUG_RETURN(TRUE);
}
break;
case FIELD_TYPE_DOUBLE:
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (!fld_length && !fld_decimals)
{
length= DBL_DIG+7;
decimals= NOT_FIXED_DEC;
}
if (length < decimals &&
decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), fld_name);
DBUG_RETURN(TRUE);
}
break;
case FIELD_TYPE_TIMESTAMP:
if (!fld_length)
length= 14; /* Full date YYYYMMDDHHMMSS */
else if (length != 19)
{
/*
We support only even TIMESTAMP lengths less or equal than 14
and 19 as length of 4.1 compatible representation.
*/
length= ((length+1)/2)*2; /* purecov: inspected */
length= min(length,14); /* purecov: inspected */
}
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
if (fld_default_value)
{
/* Grammar allows only NOW() value for ON UPDATE clause */
if (fld_default_value->type() == Item::FUNC_ITEM &&
((Item_func*)fld_default_value)->functype() == Item_func::NOW_FUNC)
{
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_DNUN_FIELD:
Field::TIMESTAMP_DN_FIELD);
/*
We don't need default value any longer moreover it is dangerous.
Everything handled by unireg_check further.
*/
def= 0;
}
else
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD:
Field::NONE);
}
else
{
/*
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
or ON UPDATE values then for the sake of compatiblity we should treat
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
have another TIMESTAMP column with auto-set option before this one)
or DEFAULT 0 (in other cases).
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
information about all TIMESTAMP fields in table will be availiable.
If we have TIMESTAMP NULL column without explicit DEFAULT value
we treat it as having DEFAULT NULL attribute.
*/
unireg_check= (fld_on_update_value ? Field::TIMESTAMP_UN_FIELD :
(flags & NOT_NULL_FLAG ? Field::TIMESTAMP_OLD_FIELD :
Field::NONE));
}
break;
case FIELD_TYPE_DATE:
/* Old date type. */
if (protocol_version != PROTOCOL_VERSION-1)
sql_type= FIELD_TYPE_NEWDATE;
/* fall trough */
case FIELD_TYPE_NEWDATE:
length= 10;
break;
case FIELD_TYPE_TIME:
length= 10;
break;
case FIELD_TYPE_DATETIME:
length= 19;
break;
case FIELD_TYPE_SET:
{
if (fld_interval_list->elements > sizeof(longlong)*8)
{
my_error(ER_TOO_BIG_SET, MYF(0), fld_name); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
pack_length= get_set_pack_length(fld_interval_list->elements);
List_iterator<String> it(*fld_interval_list);
String *tmp;
while ((tmp= it++))
interval_list.push_back(tmp);
/*
Set fake length to 1 to pass the below conditions.
Real length will be set in mysql_prepare_table()
when we know the character set of the column
*/
length= 1;
break;
}
case FIELD_TYPE_ENUM:
{
/* Should be safe. */
pack_length= get_enum_pack_length(fld_interval_list->elements);
List_iterator<String> it(*fld_interval_list);
String *tmp;
while ((tmp= it++))
interval_list.push_back(tmp);
length= 1; /* See comment for FIELD_TYPE_SET above. */
break;
}
case MYSQL_TYPE_VAR_STRING:
DBUG_ASSERT(0); /* Impossible. */
break;
case MYSQL_TYPE_BIT:
{
if (!fld_length)
length= 1;
if (length > MAX_BIT_FIELD_LENGTH)
{
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name,
MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(TRUE);
}
pack_length= (length + 7) / 8;
break;
}
case FIELD_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
}
if (!(flags & BLOB_FLAG) &&
((length > max_field_charlength && fld_type != FIELD_TYPE_SET &&
fld_type != FIELD_TYPE_ENUM &&
(fld_type != MYSQL_TYPE_VARCHAR || fld_default_value)) ||
(!length &&
fld_type != MYSQL_TYPE_STRING &&
fld_type != MYSQL_TYPE_VARCHAR && fld_type != FIELD_TYPE_GEOMETRY)))
{
my_error((fld_type == MYSQL_TYPE_VAR_STRING ||
fld_type == MYSQL_TYPE_VARCHAR ||
fld_type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
ER_TOO_BIG_DISPLAYWIDTH,
MYF(0),
fld_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(TRUE);
}
fld_type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & fld_type_modifier)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), fld_name);
DBUG_RETURN(TRUE);
}
DBUG_RETURN(FALSE); /* success */
}
enum_field_types get_blob_type_from_length(ulong length) enum_field_types get_blob_type_from_length(ulong length)
{ {
enum_field_types type; enum_field_types type;

View file

@ -134,7 +134,19 @@ public:
null_bit == field->null_bit); null_bit == field->null_bit);
} }
virtual bool eq_def(Field *field); virtual bool eq_def(Field *field);
/*
pack_length() returns size (in bytes) used to store field data in memory
(i.e. it returns the maximum size of the field in a row of the table,
which is located in RAM).
*/
virtual uint32 pack_length() const { return (uint32) field_length; } virtual uint32 pack_length() const { return (uint32) field_length; }
/*
pack_length_in_rec() returns size (in bytes) used to store field data on
storage (i.e. it returns the maximal size of the field in a row of the
table, which is located on disk).
*/
virtual uint32 pack_length_in_rec() const { return pack_length(); } virtual uint32 pack_length_in_rec() const { return pack_length(); }
virtual uint32 sort_length() const { return pack_length(); } virtual uint32 sort_length() const { return pack_length(); }
virtual void reset(void) { bzero(ptr,pack_length()); } virtual void reset(void) { bzero(ptr,pack_length()); }
@ -1410,6 +1422,12 @@ public:
void init_for_tmp_table(enum_field_types sql_type_arg, void init_for_tmp_table(enum_field_types sql_type_arg,
uint32 max_length, uint32 decimals, uint32 max_length, uint32 decimals,
bool maybe_null, bool is_unsigned); bool maybe_null, bool is_unsigned);
bool init(THD *thd, char *field_name, enum_field_types type, char *length,
char *decimals, uint type_modifier, Item *default_value,
Item *on_update_value, LEX_STRING *comment, char *change,
List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type);
}; };

View file

@ -432,7 +432,7 @@ bool federated_db_init()
DBUG_ENTER("federated_db_init"); DBUG_ENTER("federated_db_init");
if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST)) if (pthread_mutex_init(&federated_mutex, MY_MUTEX_INIT_FAST))
goto error; goto error;
if (hash_init(&federated_open_tables, system_charset_info, 32, 0, 0, if (!hash_init(&federated_open_tables, system_charset_info, 32, 0, 0,
(hash_get_key) federated_get_key, 0, 0)) (hash_get_key) federated_get_key, 0, 0))
{ {
federated_init= TRUE; federated_init= TRUE;
@ -1343,7 +1343,7 @@ static FEDERATED_SHARE *get_share(const char *table_name, TABLE *table)
query.append(FEDERATED_BTICK); query.append(FEDERATED_BTICK);
query.append(FEDERATED_COMMA); query.append(FEDERATED_COMMA);
} }
query.length(query.length()- FEDERATED_COMMA_LEN); query.length(query.length()- (FEDERATED_COMMA_LEN - 1));
query.append(FEDERATED_FROM); query.append(FEDERATED_FROM);
query.append(FEDERATED_BTICK); query.append(FEDERATED_BTICK);

View file

@ -296,23 +296,6 @@ longlong Item::val_int_from_decimal()
} }
void *Item::operator new(size_t size, Item *reuse, uint *rsize)
{
if (reuse && size <= reuse->rsize)
{
if (rsize)
(*rsize)= reuse->rsize;
reuse->cleanup();
delete reuse;
TRASH((void *)reuse, size);
return (void *)reuse;
}
if (rsize)
(*rsize)= (uint) size;
return (void *)sql_alloc((uint)size);
}
Item::Item(): Item::Item():
rsize(0), name(0), orig_name(0), name_length(0), fixed(0), rsize(0), name(0), orig_name(0), name_length(0), fixed(0),
is_autogenerated_name(TRUE), is_autogenerated_name(TRUE),
@ -802,9 +785,41 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions)
/***************************************************************************** /*****************************************************************************
Item_splocal methods Item_sp_variable methods
*****************************************************************************/ *****************************************************************************/
double Item_splocal::val_real()
Item_sp_variable::Item_sp_variable(char *sp_var_name_str,
uint sp_var_name_length)
:m_thd(0)
#ifndef DBUG_OFF
, m_sp(0)
#endif
{
m_name.str= sp_var_name_str;
m_name.length= sp_var_name_length;
}
bool Item_sp_variable::fix_fields(THD *thd, Item **)
{
Item *it;
m_thd= thd; /* NOTE: this must be set before any this_xxx() */
it= this_item();
DBUG_ASSERT(it->fixed);
max_length= it->max_length;
decimals= it->decimals;
unsigned_flag= it->unsigned_flag;
fixed= 1;
collation.set(it->collation.collation, it->collation.derivation);
return FALSE;
}
double Item_sp_variable::val_real()
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
Item *it= this_item(); Item *it= this_item();
@ -814,7 +829,7 @@ double Item_splocal::val_real()
} }
longlong Item_splocal::val_int() longlong Item_sp_variable::val_int()
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
Item *it= this_item(); Item *it= this_item();
@ -824,13 +839,14 @@ longlong Item_splocal::val_int()
} }
String *Item_splocal::val_str(String *sp) String *Item_sp_variable::val_str(String *sp)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
Item *it= this_item(); Item *it= this_item();
String *res= it->val_str(sp); String *res= it->val_str(sp);
null_value= it->null_value; null_value= it->null_value;
if (!res) if (!res)
return NULL; return NULL;
@ -854,11 +870,12 @@ String *Item_splocal::val_str(String *sp)
str_value.set(res->ptr(), res->length(), res->charset()); str_value.set(res->ptr(), res->length(), res->charset());
else else
res->mark_as_const(); res->mark_as_const();
return &str_value; return &str_value;
} }
my_decimal *Item_splocal::val_decimal(my_decimal *decimal_value) my_decimal *Item_sp_variable::val_decimal(my_decimal *decimal_value)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
Item *it= this_item(); Item *it= this_item();
@ -868,64 +885,53 @@ my_decimal *Item_splocal::val_decimal(my_decimal *decimal_value)
} }
bool Item_splocal::is_null() bool Item_sp_variable::is_null()
{ {
Item *it= this_item(); return this_item()->is_null();
return it->is_null(); }
/*****************************************************************************
Item_splocal methods
*****************************************************************************/
Item_splocal::Item_splocal(const LEX_STRING &sp_var_name,
uint sp_var_idx,
enum_field_types sp_var_type,
uint pos_in_q)
:Item_sp_variable(sp_var_name.str, sp_var_name.length),
m_var_idx(sp_var_idx), pos_in_query(pos_in_q)
{
maybe_null= TRUE;
m_type= sp_map_item_type(sp_var_type);
m_result_type= sp_map_result_type(sp_var_type);
} }
Item * Item *
Item_splocal::this_item() Item_splocal::this_item()
{ {
DBUG_ASSERT(owner == thd->spcont->owner); DBUG_ASSERT(m_sp == m_thd->spcont->sp);
return thd->spcont->get_item(m_offset);
return m_thd->spcont->get_item(m_var_idx);
}
const Item *
Item_splocal::this_item() const
{
DBUG_ASSERT(m_sp == m_thd->spcont->sp);
return m_thd->spcont->get_item(m_var_idx);
} }
Item ** Item **
Item_splocal::this_item_addr(THD *thd, Item **addr) Item_splocal::this_item_addr(THD *thd, Item **)
{ {
DBUG_ASSERT(owner == thd->spcont->owner); DBUG_ASSERT(m_sp == thd->spcont->sp);
return thd->spcont->get_item_addr(m_offset);
}
Item * return thd->spcont->get_item_addr(m_var_idx);
Item_splocal::this_const_item() const
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
Item::Type
Item_splocal::type() const
{
if (thd && thd->spcont)
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset)->type();
}
return NULL_ITEM; // Anything but SUBSELECT_ITEM
}
bool Item_splocal::fix_fields(THD *thd_arg, Item **ref)
{
Item *it;
thd= thd_arg; // Must be set before this_item()
it= this_item();
DBUG_ASSERT(it->fixed);
max_length= it->max_length;
decimals= it->decimals;
unsigned_flag= it->unsigned_flag;
fixed= 1;
return FALSE;
}
void Item_splocal::cleanup()
{
fixed= 0;
} }
@ -934,7 +940,53 @@ void Item_splocal::print(String *str)
str->reserve(m_name.length+8); str->reserve(m_name.length+8);
str->append(m_name.str, m_name.length); str->append(m_name.str, m_name.length);
str->append('@'); str->append('@');
str->qs_append(m_offset); str->qs_append(m_var_idx);
}
/*****************************************************************************
Item_case_expr methods
*****************************************************************************/
Item_case_expr::Item_case_expr(int case_expr_id)
:Item_sp_variable(STRING_WITH_LEN("case_expr")),
m_case_expr_id(case_expr_id)
{
}
Item *
Item_case_expr::this_item()
{
DBUG_ASSERT(m_sp == m_thd->spcont->sp);
return m_thd->spcont->get_case_expr(m_case_expr_id);
}
const Item *
Item_case_expr::this_item() const
{
DBUG_ASSERT(m_sp == m_thd->spcont->sp);
return m_thd->spcont->get_case_expr(m_case_expr_id);
}
Item **
Item_case_expr::this_item_addr(THD *thd, Item **)
{
DBUG_ASSERT(m_sp == thd->spcont->sp);
return thd->spcont->get_case_expr_addr(m_case_expr_id);
}
void Item_case_expr::print(String *str)
{
str->append(STRING_WITH_LEN("case_expr@"));
str->qs_append(m_case_expr_id);
} }
@ -1013,12 +1065,6 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref)
} }
void Item_name_const::cleanup()
{
fixed= 0;
}
void Item_name_const::print(String *str) void Item_name_const::print(String *str)
{ {
str->append(STRING_WITH_LEN("NAME_CONST(")); str->append(STRING_WITH_LEN("NAME_CONST("));
@ -3946,6 +3992,9 @@ int Item::save_in_field(Field *field, bool no_conversions)
str_value.set_quick(0, 0, cs); str_value.set_quick(0, 0, cs);
return set_field_to_null_with_conversions(field, no_conversions); return set_field_to_null_with_conversions(field, no_conversions);
} }
/* NOTE: If null_value == FALSE, "result" must be not NULL. */
field->set_notnull(); field->set_notnull();
error=field->store(result->ptr(),result->length(),cs); error=field->store(result->ptr(),result->length(),cs);
str_value.set_quick(0, 0, cs); str_value.set_quick(0, 0, cs);
@ -5207,7 +5256,7 @@ void Item_trigger_field::setup_field(THD *thd, TABLE *table)
set field_idx properly. set field_idx properly.
*/ */
(void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name), (void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
0, 0, &field_idx, 0); 0, &field_idx);
thd->set_query_id= save_set_query_id; thd->set_query_id= save_set_query_id;
triggers= table->triggers; triggers= table->triggers;
} }

View file

@ -326,6 +326,48 @@ struct Name_resolution_context: Sql_alloc
}; };
/*
Store and restore the current state of a name resolution context.
*/
class Name_resolution_context_state
{
private:
TABLE_LIST *save_table_list;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
public:
TABLE_LIST *save_next_local;
public:
/* Save the state of a name resolution context. */
void save_state(Name_resolution_context *context, TABLE_LIST *table_list)
{
save_table_list= context->table_list;
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
}
/* Restore a name resolution context from saved state. */
void restore_state(Name_resolution_context *context, TABLE_LIST *table_list)
{
table_list->next_local= save_next_local;
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
}
};
/*************************************************************************/ /*************************************************************************/
typedef bool (Item::*Item_processor)(byte *arg); typedef bool (Item::*Item_processor)(byte *arg);
@ -341,8 +383,6 @@ public:
{ return (void*) sql_alloc((uint) size); } { return (void*) sql_alloc((uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root) static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); } { return (void*) alloc_root(mem_root, (uint) size); }
/* Special for SP local variable assignment - reusing slots */
static void *operator new(size_t size, Item *reuse, uint *rsize);
static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root) {} static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
@ -671,13 +711,13 @@ public:
current value and pointer to current Item otherwise. current value and pointer to current Item otherwise.
*/ */
virtual Item *this_item() { return this; } virtual Item *this_item() { return this; }
virtual const Item *this_item() const { return this; }
/* /*
For SP local variable returns address of pointer to Item representing its For SP local variable returns address of pointer to Item representing its
current value and pointer passed via parameter otherwise. current value and pointer passed via parameter otherwise.
*/ */
virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; } virtual Item **this_item_addr(THD *thd, Item **addr) { return addr; }
/* For SPs mostly. */
virtual Item *this_const_item() const { return const_cast<Item*>(this); }
// Row emulation // Row emulation
virtual uint cols() { return 1; } virtual uint cols() { return 1; }
@ -706,21 +746,32 @@ public:
class sp_head; class sp_head;
/*
A reference to local SP variable (incl. reference to SP parameter), used in
runtime.
NOTE
This item has a "value" item, defined as
this_item() = thd->spcont->get_item(m_offset)
and it delegates everything to that item (if !this_item() then this item
poses as Item_null) except for name, which is the name of SP local
variable.
*/
class Item_splocal : public Item /*****************************************************************************
The class is a base class for representation of stored routine variables in
the Item-hierarchy. There are the following kinds of SP-vars:
- local variables (Item_splocal);
- CASE expression (Item_case_expr);
*****************************************************************************/
class Item_sp_variable :public Item
{ {
uint m_offset; protected:
/*
THD, which is stored in fix_fields() and is used in this_item() to avoid
current_thd use.
*/
THD *m_thd;
public:
LEX_STRING m_name;
/*
Buffer, pointing to the string value of the item. We need it to
protect internal buffer from changes. See comment to analogous
member in Item_param for more details.
*/
String str_value_ptr;
public: public:
#ifndef DBUG_OFF #ifndef DBUG_OFF
@ -728,11 +779,74 @@ public:
Routine to which this Item_splocal belongs. Used for checking if correct Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling. runtime context is used for variable handling.
*/ */
sp_head *owner; sp_head *m_sp;
#endif #endif
LEX_STRING m_name;
THD *thd;
public:
Item_sp_variable(char *sp_var_name_str, uint sp_var_name_length);
public:
bool fix_fields(THD *thd, Item **);
double val_real();
longlong val_int();
String *val_str(String *sp);
my_decimal *val_decimal(my_decimal *decimal_value);
bool is_null();
public:
inline void make_field(Send_field *field);
inline bool const_item() const;
inline int save_in_field(Field *field, bool no_conversions);
inline bool send(Protocol *protocol, String *str);
};
/*****************************************************************************
Item_sp_variable inline implementation.
*****************************************************************************/
inline void Item_sp_variable::make_field(Send_field *field)
{
Item *it= this_item();
if (name)
it->set_name(name, (uint) strlen(name), system_charset_info);
else
it->set_name(m_name.str, m_name.length, system_charset_info);
it->make_field(field);
}
inline bool Item_sp_variable::const_item() const
{
return TRUE;
}
inline int Item_sp_variable::save_in_field(Field *field, bool no_conversions)
{
return this_item()->save_in_field(field, no_conversions);
}
inline bool Item_sp_variable::send(Protocol *protocol, String *str)
{
return this_item()->send(protocol, str);
}
/*****************************************************************************
A reference to local SP variable (incl. reference to SP parameter), used in
runtime.
*****************************************************************************/
class Item_splocal :public Item_sp_variable
{
uint m_var_idx;
Type m_type;
Item_result m_result_type;
public:
/* /*
Position of this reference to SP variable in the statement (the Position of this reference to SP variable in the statement (the
statement itself is in sp_instr_stmt::m_query). statement itself is in sp_instr_stmt::m_query).
@ -745,78 +859,94 @@ public:
*/ */
uint pos_in_query; uint pos_in_query;
Item_splocal(LEX_STRING name, uint offset, uint pos_in_q=0) Item_splocal(const LEX_STRING &sp_var_name, uint sp_var_idx,
: m_offset(offset), m_name(name), thd(0), pos_in_query(pos_in_q) enum_field_types sp_var_type, uint pos_in_q= 0);
{
maybe_null= TRUE;
}
/* For error printing */
inline LEX_STRING *my_name(LEX_STRING *get_name)
{
if (!get_name)
return &m_name;
(*get_name)= m_name;
return get_name;
}
bool is_splocal() { return 1; } /* Needed for error checking */ bool is_splocal() { return 1; } /* Needed for error checking */
Item *this_item(); Item *this_item();
const Item *this_item() const;
Item **this_item_addr(THD *thd, Item **); Item **this_item_addr(THD *thd, Item **);
Item *this_const_item() const;
bool fix_fields(THD *, Item **);
void cleanup();
inline uint get_offset()
{
return m_offset;
}
// Abstract methods inherited from Item. Just defer the call to
// the item in the frame
enum Type type() const;
double val_real();
longlong val_int();
String *val_str(String *sp);
my_decimal *val_decimal(my_decimal *);
bool is_null();
void print(String *str); void print(String *str);
void make_field(Send_field *field) public:
{ inline const LEX_STRING *my_name() const;
Item *it= this_item();
if (name) inline uint get_var_idx() const;
it->set_name(name, (uint) strlen(name), system_charset_info);
else
it->set_name(m_name.str, m_name.length, system_charset_info);
it->make_field(field);
}
Item_result result_type() const inline enum Type type() const;
{ inline Item_result result_type() const;
return this_const_item()->result_type();
}
bool const_item() const
{
return TRUE;
}
int save_in_field(Field *field, bool no_conversions)
{
return this_item()->save_in_field(field, no_conversions);
}
bool send(Protocol *protocol, String *str)
{
return this_item()->send(protocol, str);
}
}; };
/*****************************************************************************
Item_splocal inline implementation.
*****************************************************************************/
inline const LEX_STRING *Item_splocal::my_name() const
{
return &m_name;
}
inline uint Item_splocal::get_var_idx() const
{
return m_var_idx;
}
inline enum Item::Type Item_splocal::type() const
{
return m_type;
}
inline Item_result Item_splocal::result_type() const
{
return m_result_type;
}
/*****************************************************************************
A reference to case expression in SP, used in runtime.
*****************************************************************************/
class Item_case_expr :public Item_sp_variable
{
public:
Item_case_expr(int case_expr_id);
public:
Item *this_item();
const Item *this_item() const;
Item **this_item_addr(THD *thd, Item **);
inline enum Type type() const;
inline Item_result result_type() const;
public:
/*
NOTE: print() is intended to be used from views and for debug.
Item_case_expr can not occur in views, so here it is only for debug
purposes.
*/
void print(String *str);
private:
int m_case_expr_id;
};
/*****************************************************************************
Item_case_expr inline implementation.
*****************************************************************************/
inline enum Item::Type Item_case_expr::type() const
{
return this_item()->type();
}
inline Item_result Item_case_expr::result_type() const
{
return this_item()->result_type();
}
/* /*
NAME_CONST(given_name, const_value). NAME_CONST(given_name, const_value).
@ -843,7 +973,6 @@ public:
} }
bool fix_fields(THD *, Item **); bool fix_fields(THD *, Item **);
void cleanup();
enum Type type() const; enum Type type() const;
double val_real(); double val_real();

View file

@ -4720,7 +4720,7 @@ Item_func_sp::sp_result_field(void) const
dummy_table->s->table_name.str= empty_name; dummy_table->s->table_name.str= empty_name;
dummy_table->s->db.str= empty_name; dummy_table->s->db.str= empty_name;
} }
field= m_sp->make_field(max_length, name, dummy_table); field= m_sp->create_result_field(max_length, name, dummy_table);
DBUG_RETURN(field); DBUG_RETURN(field);
} }
@ -4733,17 +4733,17 @@ Item_func_sp::sp_result_field(void) const
1 value = NULL or error 1 value = NULL or error
*/ */
int bool
Item_func_sp::execute(Field **flp) Item_func_sp::execute(Field **flp)
{ {
Item *it; THD *thd= current_thd;
Field *f; Field *f;
if (execute(&it))
{ /*
null_value= 1; Get field in virtual tmp table to store result. Create the field if
context->process_error(current_thd); invoked first time.
return 1; */
}
if (!(f= *flp)) if (!(f= *flp))
{ {
*flp= f= sp_result_field(); *flp= f= sp_result_field();
@ -4752,20 +4752,33 @@ Item_func_sp::execute(Field **flp)
f->null_ptr= (uchar *)&null_value; f->null_ptr= (uchar *)&null_value;
f->null_bit= 1; f->null_bit= 1;
} }
it->save_in_field(f, 1);
return null_value= f->is_null(); /* Execute function and store the return value in the field. */
if (execute_impl(thd, f))
{
null_value= 1;
context->process_error(thd);
return TRUE;
}
/* Check that the field (the value) is not NULL. */
null_value= f->is_null();
return null_value;
} }
int bool
Item_func_sp::execute(Item **itp) Item_func_sp::execute_impl(THD *thd, Field *return_value_fld)
{ {
DBUG_ENTER("Item_func_sp::execute"); bool err_status= TRUE;
THD *thd= current_thd;
int res= -1;
Sub_statement_state statement_state; Sub_statement_state statement_state;
Security_context *save_security_ctx= thd->security_ctx, *save_ctx_func; Security_context *save_security_ctx= thd->security_ctx, *save_ctx_func;
DBUG_ENTER("Item_func_sp::execute_impl");
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
if (context->security_ctx) if (context->security_ctx)
{ {
@ -4782,7 +4795,7 @@ Item_func_sp::execute(Item **itp)
function call into binlog. function call into binlog.
*/ */
thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION); thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
res= m_sp->execute_function(thd, args, arg_count, itp); err_status= m_sp->execute_function(thd, args, arg_count, return_value_fld);
thd->restore_sub_statement_state(&statement_state); thd->restore_sub_statement_state(&statement_state);
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
@ -4792,7 +4805,7 @@ error:
#else #else
error: error:
#endif #endif
DBUG_RETURN(res); DBUG_RETURN(err_status);
} }
@ -4888,7 +4901,7 @@ Item_func_sp::tmp_table_field(TABLE *t_arg)
DBUG_ENTER("Item_func_sp::tmp_table_field"); DBUG_ENTER("Item_func_sp::tmp_table_field");
if (m_sp) if (m_sp)
res= m_sp->make_field(max_length, (const char *)name, t_arg); res= m_sp->create_result_field(max_length, (const char*) name, t_arg);
if (!res) if (!res)
res= Item_func::tmp_table_field(t_arg); res= Item_func::tmp_table_field(t_arg);

View file

@ -1374,8 +1374,8 @@ private:
Field *result_field; Field *result_field;
char result_buf[64]; char result_buf[64];
int execute(Item **itp); bool execute(Field **flp);
int execute(Field **flp); bool execute_impl(THD *thd, Field *return_value_fld);
Field *sp_result_field(void) const; Field *sp_result_field(void) const;
public: public:

View file

@ -686,6 +686,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list); bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache, int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
KEY_CACHE *dst_cache); KEY_CACHE *dst_cache);
TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list);
bool mysql_xa_recover(THD *thd); bool mysql_xa_recover(THD *thd);
@ -820,18 +821,15 @@ find_field_in_tables(THD *thd, Item_ident *item,
bool check_privileges, bool register_tree_change); bool check_privileges, bool register_tree_change);
Field * Field *
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name, const char *name, uint length,
const char *table_name, const char *db_name, const char *item_name, const char *db_name,
uint length, Item **ref, const char *table_name, Item **ref,
bool check_grants_table, bool check_grants_view, bool check_privileges, bool allow_rowid,
bool allow_rowid,
uint *cached_field_index_ptr, uint *cached_field_index_ptr,
bool register_tree_change, TABLE_LIST **actual_table); bool register_tree_change, TABLE_LIST **actual_table);
Field * Field *
find_field_in_table(THD *thd, TABLE *table, const char *name, find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
uint length, bool check_grants, bool allow_rowid, bool allow_rowid, uint *cached_field_index_ptr);
uint *cached_field_index_ptr,
Security_context *sctx);
Field * Field *
find_field_in_table_sef(TABLE *table, const char *name); find_field_in_table_sef(TABLE *table, const char *name);
@ -950,8 +948,9 @@ create_field * new_create_field(THD *thd, char *field_name, enum_field_types typ
uint uint_geom_type); uint uint_geom_type);
void store_position_for_column(const char *name); void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc); bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
Name_resolution_context *make_join_on_context(THD *thd, TABLE_LIST *left_op, bool push_new_name_resolution_context(THD *thd,
TABLE_LIST *right_op); TABLE_LIST *left_op,
TABLE_LIST *right_op);
void add_join_on(TABLE_LIST *b,Item *expr); void add_join_on(TABLE_LIST *b,Item *expr);
void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields); void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item); bool add_proc_to_list(THD *thd, Item *item);
@ -1140,8 +1139,8 @@ void unhex_type2(TYPELIB *lib);
uint check_word(TYPELIB *lib, const char *val, const char *end, uint check_word(TYPELIB *lib, const char *val, const char *end,
const char **end_of_word); const char **end_of_word);
bool is_keyword(const char *name, uint len);
bool is_keyword(const char *name, uint len);
#define MY_DB_OPT_FILE "db.opt" #define MY_DB_OPT_FILE "db.opt"
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create); bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);

View file

@ -4697,12 +4697,12 @@ Disable with --skip-bdb (will save memory).",
{"bdb-lock-detect", OPT_BDB_LOCK, {"bdb-lock-detect", OPT_BDB_LOCK,
"Berkeley lock detect (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec).", "Berkeley lock detect (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-logdir", OPT_BDB_LOG, "Berkeley DB log file directory.",
(gptr*) &berkeley_logdir, (gptr*) &berkeley_logdir, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-log-direct", OPT_BDB_LOG_DIRECT, {"bdb-log-direct", OPT_BDB_LOG_DIRECT,
"Turn off system buffering of BDB log files to avoid double caching.", "Turn off system buffering of BDB log files to avoid double caching.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-logdir", OPT_BDB_LOG, "Berkeley DB log file directory.",
(gptr*) &berkeley_logdir, (gptr*) &berkeley_logdir, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-no-recover", OPT_BDB_NO_RECOVER, {"bdb-no-recover", OPT_BDB_NO_RECOVER,
"Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG, "Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0}, NO_ARG, 0, 0, 0, 0, 0, 0},

View file

@ -791,9 +791,9 @@ struct show_var_st init_vars[]= {
{sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads, {sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
SHOW_SYS}, SHOW_SYS},
{sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS}, {sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
{sys_myisam_use_mmap.name, (char*) &sys_myisam_use_mmap, SHOW_SYS},
{sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS}, {sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS},
{sys_myisam_use_mmap.name, (char*) &sys_myisam_use_mmap, SHOW_SYS},
#ifdef __NT__ #ifdef __NT__
{"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL}, {"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL},
@ -885,8 +885,8 @@ struct show_var_st init_vars[]= {
{"system_time_zone", system_time_zone, SHOW_CHAR}, {"system_time_zone", system_time_zone, SHOW_CHAR},
#endif #endif
{"table_definition_cache", (char*) &table_def_size, SHOW_LONG}, {"table_definition_cache", (char*) &table_def_size, SHOW_LONG},
{"table_open_cache", (char*) &table_cache_size, SHOW_LONG},
{"table_lock_wait_timeout", (char*) &table_lock_wait_timeout, SHOW_LONG }, {"table_lock_wait_timeout", (char*) &table_lock_wait_timeout, SHOW_LONG },
{"table_open_cache", (char*) &table_cache_size, SHOW_LONG},
{sys_table_type.name, (char*) &sys_table_type, SHOW_SYS}, {sys_table_type.name, (char*) &sys_table_type, SHOW_SYS},
{sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS}, {sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS},
#ifdef HAVE_THR_SETCONCURRENCY #ifdef HAVE_THR_SETCONCURRENCY

View file

@ -4590,7 +4590,7 @@ ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 21000
nla "De gebruikte SELECT commando's hebben een verschillend aantal kolommen" nla "De gebruikte SELECT commando's hebben een verschillend aantal kolommen"
eng "The used SELECT statements have a different number of columns" eng "The used SELECT statements have a different number of columns"
est "Tulpade arv kasutatud SELECT lausetes ei kattu" est "Tulpade arv kasutatud SELECT lausetes ei kattu"
ger "Die verwendeten SELECT-Befehle liefern eine unterschiedliche Anzahl von Feldern zurück" ger "Die verwendeten SELECT-Befehle liefern unterschiedliche Anzahlen von Feldern zurück"
ita "La SELECT utilizzata ha un numero di colonne differente" ita "La SELECT utilizzata ha un numero di colonne differente"
por "Os comandos SELECT usados têm diferente número de colunas" por "Os comandos SELECT usados têm diferente número de colunas"
rus "éÓÐÏÌØÚÏ×ÁÎÎÙÅ ÏÐÅÒÁÔÏÒÙ ×ÙÂÏÒËÉ (SELECT) ÄÁÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×" rus "éÓÐÏÌØÚÏ×ÁÎÎÙÅ ÏÐÅÒÁÔÏÒÙ ×ÙÂÏÒËÉ (SELECT) ÄÁÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×"
@ -5271,7 +5271,7 @@ ER_VIEW_SELECT_TMPTABLE
ukr "View SELECT ×ÉËÏÒÉÓÔÏ×Õ¤ ÔÉÍÞÁÓÏ×Õ ÔÁÂÌÉÃÀ '%-.64s'" ukr "View SELECT ×ÉËÏÒÉÓÔÏ×Õ¤ ÔÉÍÞÁÓÏ×Õ ÔÁÂÌÉÃÀ '%-.64s'"
ER_VIEW_WRONG_LIST ER_VIEW_WRONG_LIST
eng "View's SELECT and view's field list have different column counts" eng "View's SELECT and view's field list have different column counts"
ger "SELECT- und Feldliste der Views haben eine unterschiedliche Anzahl von Spalten" ger "SELECT- und Feldliste der Views haben unterschiedliche Anzahlen von Spalten"
rus "View SELECT É ÓÐÉÓÏË ÐÏÌÅÊ view ÉÍÅÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×" rus "View SELECT É ÓÐÉÓÏË ÐÏÌÅÊ view ÉÍÅÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×"
ukr "View SELECT ¦ ÐÅÒÅÌ¦Ë ÓÔÏ×ÂÃ¦× view ÍÁÀÔØ Ò¦ÚÎÕ Ë¦ÌØ˦ÓÔØ ÓËÏ×Âæ×" ukr "View SELECT ¦ ÐÅÒÅÌ¦Ë ÓÔÏ×ÂÃ¦× view ÍÁÀÔØ Ò¦ÚÎÕ Ë¦ÌØ˦ÓÔØ ÓËÏ×Âæ×"
ER_WARN_VIEW_MERGE ER_WARN_VIEW_MERGE
@ -5482,7 +5482,7 @@ ER_CANT_CREATE_GEOMETRY_OBJECT 22003
ger "Kann kein Geometrieobjekt aus den Daten machen, die Sie dem GEOMETRY-Feld übergeben haben" ger "Kann kein Geometrieobjekt aus den Daten machen, die Sie dem GEOMETRY-Feld übergeben haben"
ER_FAILED_ROUTINE_BREAK_BINLOG ER_FAILED_ROUTINE_BREAK_BINLOG
eng "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes" eng "A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes"
ger "Eine Routine, die weder NO SQL noch READS SQL DATA in der Deklaration hat, schlug fehl und Binärlogging ist aktiv. Wenn Nicht-Transaktions-Tabellen atualisiert wurden, enthält das Binärlog ihre Änderungen nicht" ger "Eine Routine, die weder NO SQL noch READS SQL DATA in der Deklaration hat, schlug fehl und Binärlogging ist aktiv. Wenn Nicht-Transaktions-Tabellen aktualisiert wurden, enthält das Binärlog ihre Änderungen nicht"
ER_BINLOG_UNSAFE_ROUTINE ER_BINLOG_UNSAFE_ROUTINE
eng "This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)" eng "This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)"
ger "Diese Routine hat weder DETERMINISTIC, NO SQL noch READS SQL DATA in der Deklaration und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)" ger "Diese Routine hat weder DETERMINISTIC, NO SQL noch READS SQL DATA in der Deklaration und Binärlogging ist aktiv (*vielleicht* sollten Sie die weniger sichere Variable log_bin_trust_routine_creators verwenden)"
@ -5593,10 +5593,15 @@ ER_SP_BAD_VAR_SHADOW 42000
ger "Variable '%-.64s' muss mit `...` geschützt oder aber umbenannt werden" ger "Variable '%-.64s' muss mit `...` geschützt oder aber umbenannt werden"
ER_TRG_NO_DEFINER ER_TRG_NO_DEFINER
eng "No definer attribute for trigger '%-.64s'.'%-.64s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger." eng "No definer attribute for trigger '%-.64s'.'%-.64s'. The trigger will be activated under the authorization of the invoker, which may have insufficient privileges. Please recreate the trigger."
ger "Kein Definierer-Attribut für Trigger '%-.64s'.'%-.64s'. Der Trigger wird mit der Autorisierung des Aufrufers aktiviert, der möglicherweise keine zureichenden Berechtigungen hat. Bitte legen Sie den Trigger neu an."
ER_OLD_FILE_FORMAT ER_OLD_FILE_FORMAT
eng "'%-.64s' has an old format, you should re-create the '%s' object(s)" eng "'%-.64s' has an old format, you should re-create the '%s' object(s)"
ger "'%-.64s' hat altes Format, Sie sollten die '%s'-Objekt(e) neu erzeugen"
ER_SP_RECURSION_LIMIT ER_SP_RECURSION_LIMIT
eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.64s" eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was exceeded for routine %.64s"
ger "Rekursionsgrenze %d (durch Variable max_sp_recursion_depth gegeben) wurde für Routine %.64s überschritten"
ER_SP_PROC_TABLE_CORRUPT
eng "Failed to load routine %s. The table mysql.proc is missing, corrupt, or contains bad data (internal code %d)"
ER_PARTITION_REQUIRES_VALUES_ERROR ER_PARTITION_REQUIRES_VALUES_ERROR
eng "%s PARTITIONING requires definition of VALUES %s for each partition" eng "%s PARTITIONING requires definition of VALUES %s for each partition"
swe "%s PARTITIONering kräver definition av VALUES %s för varje partition" swe "%s PARTITIONering kräver definition av VALUES %s för varje partition"

107
sql/sp.cc
View file

@ -468,7 +468,7 @@ sp_returns_type(THD *thd, String &result, sp_head *sp)
bzero((char*) &share, sizeof(share)); bzero((char*) &share, sizeof(share));
table.in_use= thd; table.in_use= thd;
table.s = &share; table.s = &share;
field= sp->make_field(0, 0, &table); field= sp->create_result_field(0, 0, &table);
field->sql_type(result); field->sql_type(result);
delete field; delete field;
} }
@ -1447,21 +1447,23 @@ static void sp_update_stmt_used_routines(THD *thd, LEX *lex, SQL_LIST *src)
first_no_prelock - If true, don't add tables or cache routines used by first_no_prelock - If true, don't add tables or cache routines used by
the body of the first routine (i.e. *start) the body of the first routine (i.e. *start)
will be executed in non-prelocked mode. will be executed in non-prelocked mode.
tabs_changed - Set to TRUE some tables were added, FALSE otherwise
NOTE NOTE
If some function is missing this won't be reported here. If some function is missing this won't be reported here.
Instead this fact will be discovered during query execution. Instead this fact will be discovered during query execution.
RETURN VALUE RETURN VALUE
TRUE - some tables were added 0 - success
FALSE - no tables were added. non-0 - failure
*/ */
static bool static int
sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex, sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
Sroutine_hash_entry *start, Sroutine_hash_entry *start,
bool first_no_prelock) bool first_no_prelock, bool *tabs_changed)
{ {
bool result= FALSE; int ret= 0;
bool tabschnd= 0; /* Set if tables changed */
bool first= TRUE; bool first= TRUE;
DBUG_ENTER("sp_cache_routines_and_add_tables_aux"); DBUG_ENTER("sp_cache_routines_and_add_tables_aux");
@ -1482,12 +1484,50 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
name.m_name.str+= 1; name.m_name.str+= 1;
name.m_name.length= name.m_qname.length - name.m_db.length - 1; name.m_name.length= name.m_qname.length - name.m_db.length - 1;
if (db_find_routine(thd, type, &name, &sp) == SP_OK) switch ((ret= db_find_routine(thd, type, &name, &sp)))
{ {
if (type == TYPE_ENUM_FUNCTION) case SP_OK:
sp_cache_insert(&thd->sp_func_cache, sp); {
else if (type == TYPE_ENUM_FUNCTION)
sp_cache_insert(&thd->sp_proc_cache, sp); sp_cache_insert(&thd->sp_func_cache, sp);
else
sp_cache_insert(&thd->sp_proc_cache, sp);
}
break;
case SP_KEY_NOT_FOUND:
ret= SP_OK;
break;
case SP_OPEN_TABLE_FAILED:
/*
Force it to attempt opening it again on subsequent calls;
otherwise we will get one error message the first time, and
then ER_SP_PROC_TABLE_CORRUPT (below) on subsequent tries.
*/
mysql_proc_table_exists= 1;
/* Fall through */
default:
/*
Any error when loading an existing routine is either some problem
with the mysql.proc table, or a parse error because the contents
has been tampered with (in which case we clear that error).
*/
if (ret == SP_PARSE_ERROR)
thd->clear_error();
/*
If we cleared the parse error, or when db_find_routine() flagged
an error with it's return value without calling my_error(), we
set the generic "mysql.proc table corrupt" error here.
*/
if (!thd->net.report_error)
{
char n[NAME_LEN*2+2];
/* m_qname.str is not always \0 terminated */
memcpy(n, name.m_qname.str, name.m_qname.length);
n[name.m_qname.length]= '\0';
my_error(ER_SP_PROC_TABLE_CORRUPT, MYF(0), n, ret);
}
break;
} }
} }
if (sp) if (sp)
@ -1495,12 +1535,15 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
if (!(first && first_no_prelock)) if (!(first && first_no_prelock))
{ {
sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines); sp_update_stmt_used_routines(thd, lex, &sp->m_sroutines);
result|= sp->add_used_tables_to_table_list(thd, &lex->query_tables_last); tabschnd|=
sp->add_used_tables_to_table_list(thd, &lex->query_tables_last);
} }
} }
first= FALSE; first= FALSE;
} }
DBUG_RETURN(result); if (tabs_changed) /* it can be NULL */
*tabs_changed= tabschnd;
DBUG_RETURN(ret);
} }
@ -1515,18 +1558,20 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
lex - LEX representing statement lex - LEX representing statement
first_no_prelock - If true, don't add tables or cache routines used by first_no_prelock - If true, don't add tables or cache routines used by
the body of the first routine (i.e. *start) the body of the first routine (i.e. *start)
tabs_changed - Set to TRUE some tables were added, FALSE otherwise
RETURN VALUE RETURN VALUE
TRUE - some tables were added 0 - success
FALSE - no tables were added. non-0 - failure
*/ */
bool int
sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock) sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock,
bool *tabs_changed)
{ {
return sp_cache_routines_and_add_tables_aux(thd, lex, return sp_cache_routines_and_add_tables_aux(thd, lex,
(Sroutine_hash_entry *)lex->sroutines_list.first, (Sroutine_hash_entry *)lex->sroutines_list.first,
first_no_prelock); first_no_prelock, tabs_changed);
} }
@ -1540,16 +1585,21 @@ sp_cache_routines_and_add_tables(THD *thd, LEX *lex, bool first_no_prelock)
thd - thread context thd - thread context
lex - LEX representing statement lex - LEX representing statement
aux_lex - LEX representing view aux_lex - LEX representing view
RETURN VALUE
0 - success
non-0 - failure
*/ */
void int
sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex) sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
{ {
Sroutine_hash_entry **last_cached_routine_ptr= Sroutine_hash_entry **last_cached_routine_ptr=
(Sroutine_hash_entry **)lex->sroutines_list.next; (Sroutine_hash_entry **)lex->sroutines_list.next;
sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines_list); sp_update_stmt_used_routines(thd, lex, &aux_lex->sroutines_list);
(void)sp_cache_routines_and_add_tables_aux(thd, lex, return sp_cache_routines_and_add_tables_aux(thd, lex,
*last_cached_routine_ptr, FALSE); *last_cached_routine_ptr, FALSE,
NULL);
} }
@ -1563,12 +1613,18 @@ sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, LEX *aux_lex)
thd - thread context thd - thread context
lex - LEX respresenting statement lex - LEX respresenting statement
triggers - triggers of the table triggers - triggers of the table
RETURN VALUE
0 - success
non-0 - failure
*/ */
void int
sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers) Table_triggers_list *triggers)
{ {
int ret= 0;
if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key)) if (add_used_routine(lex, thd->stmt_arena, &triggers->sroutines_key))
{ {
Sroutine_hash_entry **last_cached_routine_ptr= Sroutine_hash_entry **last_cached_routine_ptr=
@ -1586,10 +1642,11 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
} }
} }
} }
(void)sp_cache_routines_and_add_tables_aux(thd, lex, ret= sp_cache_routines_and_add_tables_aux(thd, lex,
*last_cached_routine_ptr, *last_cached_routine_ptr,
FALSE); FALSE, NULL);
} }
return ret;
} }

View file

@ -84,11 +84,11 @@ void sp_add_used_routine(LEX *lex, Query_arena *arena,
sp_name *rt, char rt_type); sp_name *rt, char rt_type);
void sp_remove_not_own_routines(LEX *lex); void sp_remove_not_own_routines(LEX *lex);
void sp_update_sp_used_routines(HASH *dst, HASH *src); void sp_update_sp_used_routines(HASH *dst, HASH *src);
bool sp_cache_routines_and_add_tables(THD *thd, LEX *lex, int sp_cache_routines_and_add_tables(THD *thd, LEX *lex,
bool first_no_prelock); bool first_no_prelock, bool *tabs_changed);
void sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex, int sp_cache_routines_and_add_tables_for_view(THD *thd, LEX *lex,
LEX *aux_lex); LEX *aux_lex);
void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers); Table_triggers_list *triggers);
extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first); extern "C" byte* sp_sroutine_key(const byte *ptr, uint *plen, my_bool first);

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,9 @@
Item_result Item_result
sp_map_result_type(enum enum_field_types type); sp_map_result_type(enum enum_field_types type);
Item::Type
sp_map_item_type(enum enum_field_types type);
uint uint
sp_get_flags_for_command(LEX *lex); sp_get_flags_for_command(LEX *lex);
@ -123,12 +126,9 @@ public:
/* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */ /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */
int m_type; int m_type;
uint m_flags; // Boolean attributes of a stored routine uint m_flags; // Boolean attributes of a stored routine
enum enum_field_types m_returns; // For FUNCTIONs only
Field::geometry_type m_geom_returns; create_field m_return_field_def; /* This is used for FUNCTIONs only. */
CHARSET_INFO *m_returns_cs; // For FUNCTIONs only
TYPELIB *m_returns_typelib; // For FUNCTIONs only
uint m_returns_len; // For FUNCTIONs only
uint m_returns_pack; // For FUNCTIONs only
const uchar *m_tmp_query; // Temporary pointer to sub query string const uchar *m_tmp_query; // Temporary pointer to sub query string
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics; st_sp_chistics *m_chistics;
@ -202,9 +202,6 @@ public:
void void
init_strings(THD *thd, LEX *lex, sp_name *name); init_strings(THD *thd, LEX *lex, sp_name *name);
TYPELIB *
create_typelib(List<String> *src);
int int
create(THD *thd); create(THD *thd);
@ -214,10 +211,10 @@ public:
void void
destroy(); destroy();
int bool
execute_function(THD *thd, Item **args, uint argcount, Item **resp); execute_function(THD *thd, Item **args, uint argcount, Field *return_fld);
int bool
execute_procedure(THD *thd, List<Item> *args); execute_procedure(THD *thd, List<Item> *args);
int int
@ -278,7 +275,12 @@ public:
char *create_string(THD *thd, ulong *lenp); char *create_string(THD *thd, ulong *lenp);
Field *make_field(uint max_length, const char *name, TABLE *dummy); Field *create_result_field(uint field_max_length, const char *field_name,
TABLE *table);
bool fill_field_definition(THD *thd, LEX *lex,
enum enum_field_types field_type,
create_field *field_def);
void set_info(longlong created, longlong modified, void set_info(longlong created, longlong modified,
st_sp_chistics *chistics, ulong sql_mode); st_sp_chistics *chistics, ulong sql_mode);
@ -363,7 +365,7 @@ private:
*/ */
HASH m_sptabs; HASH m_sptabs;
int bool
execute(THD *thd); execute(THD *thd);
/* /*
@ -1074,6 +1076,31 @@ private:
}; // class sp_instr_error : public sp_instr }; // class sp_instr_error : public sp_instr
class sp_instr_set_case_expr :public sp_instr
{
public:
sp_instr_set_case_expr(uint ip, sp_pcontext *ctx, uint case_expr_id,
Item *case_expr, LEX *lex)
:sp_instr(ip, ctx), m_case_expr_id(case_expr_id), m_case_expr(case_expr),
m_lex_keeper(lex, TRUE)
{}
virtual int execute(THD *thd, uint *nextp);
virtual int exec_core(THD *thd, uint *nextp);
virtual void print(String *str);
private:
uint m_case_expr_id;
Item *m_case_expr;
sp_lex_keeper m_lex_keeper;
}; // class sp_instr_set_case_expr : public sp_instr
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
bool bool
sp_change_security_context(THD *thd, sp_head *sp, sp_change_security_context(THD *thd, sp_head *sp,
@ -1086,8 +1113,10 @@ TABLE_LIST *
sp_add_to_query_tables(THD *thd, LEX *lex, sp_add_to_query_tables(THD *thd, LEX *lex,
const char *db, const char *name, const char *db, const char *name,
thr_lock_type locktype); thr_lock_type locktype);
Item *
sp_prepare_func_item(THD* thd, Item **it_addr);
Item *sp_eval_func_item(THD *thd, Item **it, enum_field_types type, bool
Item *reuse, bool use_callers_arena); sp_eval_expr(THD *thd, Field *result_field, Item *expr_item);
#endif /* _SP_HEAD_H_ */ #endif /* _SP_HEAD_H_ */

View file

@ -51,21 +51,26 @@ sp_cond_check(LEX_STRING *sqlstate)
} }
sp_pcontext::sp_pcontext(sp_pcontext *prev) sp_pcontext::sp_pcontext(sp_pcontext *prev)
: Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0), :Sql_alloc(), m_total_pvars(0), m_csubsize(0), m_hsubsize(0),
m_handlers(0), m_parent(prev), m_pboundary(0) m_handlers(0), m_parent(prev), m_pboundary(0)
{ {
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), 16, 8));
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8)); VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
VOID(my_init_dynamic_array(&m_handler, sizeof(sp_cond_type_t *), 16, 8)); VOID(my_init_dynamic_array(&m_handler, sizeof(sp_cond_type_t *), 16, 8));
m_label.empty(); m_label.empty();
m_children.empty(); m_children.empty();
if (!prev) if (!prev)
{
m_poffset= m_coffset= 0; m_poffset= m_coffset= 0;
m_num_case_exprs= 0;
}
else else
{ {
m_poffset= prev->current_pvars(); m_poffset= prev->m_poffset + prev->m_total_pvars;
m_coffset= prev->current_cursors(); m_coffset= prev->current_cursors();
m_num_case_exprs= prev->get_num_case_exprs();
} }
} }
@ -81,6 +86,7 @@ sp_pcontext::destroy()
m_children.empty(); m_children.empty();
m_label.empty(); m_label.empty();
delete_dynamic(&m_pvar); delete_dynamic(&m_pvar);
delete_dynamic(&m_case_expr_id_lst);
delete_dynamic(&m_cond); delete_dynamic(&m_cond);
delete_dynamic(&m_cursor); delete_dynamic(&m_cursor);
delete_dynamic(&m_handler); delete_dynamic(&m_handler);
@ -99,16 +105,19 @@ sp_pcontext::push_context()
sp_pcontext * sp_pcontext *
sp_pcontext::pop_context() sp_pcontext::pop_context()
{ {
uint submax= max_pvars(); m_parent->m_total_pvars= m_parent->m_total_pvars + m_total_pvars;
if (submax > m_parent->m_psubsize) uint submax= max_handlers();
m_parent->m_psubsize= submax;
submax= max_handlers();
if (submax > m_parent->m_hsubsize) if (submax > m_parent->m_hsubsize)
m_parent->m_hsubsize= submax; m_parent->m_hsubsize= submax;
submax= max_cursors(); submax= max_cursors();
if (submax > m_parent->m_csubsize) if (submax > m_parent->m_csubsize)
m_parent->m_csubsize= submax; m_parent->m_csubsize= submax;
if (m_num_case_exprs > m_parent->m_num_case_exprs)
m_parent->m_num_case_exprs= m_num_case_exprs;
return m_parent; return m_parent;
} }
@ -191,26 +200,29 @@ sp_pcontext::find_pvar(uint offset)
return NULL; // index out of bounds return NULL; // index out of bounds
} }
void sp_pvar_t *
sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
sp_param_mode_t mode) sp_param_mode_t mode)
{ {
sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t)); sp_pvar_t *p= (sp_pvar_t *)sql_alloc(sizeof(sp_pvar_t));
if (p) if (!p)
{ return NULL;
if (m_pvar.elements == m_psubsize)
m_psubsize+= 1; ++m_total_pvars;
p->name.str= name->str;
p->name.length= name->length; p->name.str= name->str;
p->type= type; p->name.length= name->length;
p->mode= mode; p->type= type;
p->offset= current_pvars(); p->mode= mode;
p->dflt= NULL; p->offset= current_pvars();
insert_dynamic(&m_pvar, (gptr)&p); p->dflt= NULL;
} insert_dynamic(&m_pvar, (gptr)&p);
return p;
} }
sp_label_t * sp_label_t *
sp_pcontext::push_label(char *name, uint ip) sp_pcontext::push_label(char *name, uint ip)
{ {
@ -354,6 +366,29 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
return FALSE; return FALSE;
} }
void
sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst)
{
/* Put local/context fields in the result list. */
for (uint i = 0; i < m_pvar.elements; ++i)
{
sp_pvar_t *var_def;
get_dynamic(&m_pvar, (gptr) &var_def, i);
field_def_lst->push_back(&var_def->field_def);
}
/* Put the fields of the enclosed contexts in the result list. */
List_iterator_fast<sp_pcontext> li(m_children);
sp_pcontext *ctx;
while ((ctx = li++))
ctx->retrieve_field_definitions(field_def_lst);
}
/* /*
Find a cursor by offset from the top. Find a cursor by offset from the top.
This is only used for debugging. This is only used for debugging.

View file

@ -34,8 +34,16 @@ typedef struct sp_pvar
LEX_STRING name; LEX_STRING name;
enum enum_field_types type; enum enum_field_types type;
sp_param_mode_t mode; sp_param_mode_t mode;
uint offset; // Offset in current frame
/*
offset -- basically, this is an index of variable in the scope of root
parsing context. This means, that all variables in a stored routine
have distinct indexes/offsets.
*/
uint offset;
Item *dflt; Item *dflt;
create_field field_def;
} sp_pvar_t; } sp_pvar_t;
@ -114,9 +122,9 @@ class sp_pcontext : public Sql_alloc
// //
inline uint inline uint
max_pvars() total_pvars()
{ {
return m_psubsize + m_pvar.elements; return m_total_pvars;
} }
inline uint inline uint
@ -155,16 +163,15 @@ class sp_pcontext : public Sql_alloc
p->dflt= it; p->dflt= it;
} }
void sp_pvar_t *
push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode); push_pvar(LEX_STRING *name, enum enum_field_types type, sp_param_mode_t mode);
// Pop the last 'num' slots of the frame /*
inline void Retrieve definitions of fields from the current context and its
pop_pvar(uint num = 1) children.
{ */
while (num--) void
pop_dynamic(&m_pvar); retrieve_field_definitions(List<create_field> *field_def_lst);
}
// Find by name // Find by name
sp_pvar_t * sp_pvar_t *
@ -175,7 +182,7 @@ class sp_pcontext : public Sql_alloc
find_pvar(uint offset); find_pvar(uint offset);
/* /*
Set the current scope boundary (for default values) Set the current scope boundary (for default values).
The argument is the number of variables to skip. The argument is the number of variables to skip.
*/ */
inline void inline void
@ -184,6 +191,45 @@ class sp_pcontext : public Sql_alloc
m_pboundary= n; m_pboundary= n;
} }
/*
CASE expressions support.
*/
inline int
register_case_expr()
{
return m_num_case_exprs++;
}
inline int
get_num_case_exprs() const
{
return m_num_case_exprs;
}
inline bool
push_case_expr_id(int case_expr_id)
{
return insert_dynamic(&m_case_expr_id_lst, (gptr) &case_expr_id);
}
inline void
pop_case_expr_id()
{
pop_dynamic(&m_case_expr_id_lst);
}
inline int
get_current_case_expr_id() const
{
int case_expr_id;
get_dynamic((DYNAMIC_ARRAY*)&m_case_expr_id_lst, (gptr) &case_expr_id,
m_case_expr_id_lst.elements - 1);
return case_expr_id;
}
// //
// Labels // Labels
// //
@ -280,8 +326,18 @@ class sp_pcontext : public Sql_alloc
protected: protected:
/*
m_total_pvars -- number of variables (including all types of arguments)
in this context including all children contexts.
m_total_pvars >= m_pvar.elements.
m_total_pvars of the root parsing context contains number of all
variables (including arguments) in all enclosed contexts.
*/
uint m_total_pvars;
// The maximum sub context's framesizes // The maximum sub context's framesizes
uint m_psubsize;
uint m_csubsize; uint m_csubsize;
uint m_hsubsize; uint m_hsubsize;
uint m_handlers; // No. of handlers in this context uint m_handlers; // No. of handlers in this context
@ -290,8 +346,19 @@ private:
sp_pcontext *m_parent; // Parent context sp_pcontext *m_parent; // Parent context
uint m_poffset; // Variable offset for this context /*
m_poffset -- basically, this is an index of the first variable in this
parsing context.
m_poffset is 0 for root context.
Since now each variable is stored in separate place, no reuse is done,
so m_poffset is different for all enclosed contexts.
*/
uint m_poffset;
uint m_coffset; // Cursor offset for this context uint m_coffset; // Cursor offset for this context
/* /*
Boundary for finding variables in this context. This is the number Boundary for finding variables in this context. This is the number
of variables currently "invisible" to default clauses. of variables currently "invisible" to default clauses.
@ -300,7 +367,10 @@ private:
*/ */
uint m_pboundary; uint m_pboundary;
int m_num_case_exprs;
DYNAMIC_ARRAY m_pvar; // Parameters/variables DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_case_expr_id_lst; /* Stack of CASE expression ids. */
DYNAMIC_ARRAY m_cond; // Conditions DYNAMIC_ARRAY m_cond; // Conditions
DYNAMIC_ARRAY m_cursor; // Cursors DYNAMIC_ARRAY m_cursor; // Cursors
DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates

View file

@ -29,41 +29,137 @@
#include "sp_rcontext.h" #include "sp_rcontext.h"
#include "sp_pcontext.h" #include "sp_pcontext.h"
sp_rcontext::sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax)
: m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0), sp_rcontext::sp_rcontext(sp_pcontext *root_parsing_ctx,
m_ihsp(0), m_hfound(-1), m_ccount(0), m_prev_ctx(prev) Field *return_value_fld,
sp_rcontext *prev_runtime_ctx)
:m_root_parsing_ctx(root_parsing_ctx),
m_var_table(0),
m_var_items(0),
m_return_value_fld(return_value_fld),
m_return_value_set(FALSE),
m_hcount(0),
m_hsp(0),
m_ihsp(0),
m_hfound(-1),
m_ccount(0),
m_case_expr_holders(0),
m_prev_runtime_ctx(prev_runtime_ctx)
{ {
m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t));
m_hstack= (uint *)sql_alloc(hmax * sizeof(uint));
m_in_handler= (uint *)sql_alloc(hmax * sizeof(uint));
m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *));
m_saved.empty();
} }
int sp_rcontext::~sp_rcontext()
sp_rcontext::set_item_eval(THD *thd, uint idx, Item **item_addr,
enum_field_types type)
{ {
Item *it; if (m_var_table)
Item *reuse_it; free_blobs(m_var_table);
/* sp_eval_func_item will use callers_arena */ }
int res;
reuse_it= get_item(idx);
it= sp_eval_func_item(thd, item_addr, type, reuse_it, TRUE); /*
if (! it) Initialize sp_rcontext instance.
res= -1;
else SYNOPSIS
thd Thread handle
RETURN
FALSE on success
TRUE on error
*/
bool sp_rcontext::init(THD *thd)
{
if (init_var_table(thd) || init_var_items())
return TRUE;
return
!(m_handler=
(sp_handler_t*)thd->alloc(m_root_parsing_ctx->max_handlers() *
sizeof(sp_handler_t))) ||
!(m_hstack=
(uint*)thd->alloc(m_root_parsing_ctx->max_handlers() *
sizeof(uint))) ||
!(m_in_handler=
(uint*)thd->alloc(m_root_parsing_ctx->max_handlers() *
sizeof(uint))) ||
!(m_cstack=
(sp_cursor**)thd->alloc(m_root_parsing_ctx->max_cursors() *
sizeof(sp_cursor*))) ||
!(m_case_expr_holders=
(Item_cache**)thd->calloc(m_root_parsing_ctx->get_num_case_exprs() *
sizeof (Item_cache*)));
}
/*
Create and initialize a table to store SP-vars.
SYNOPSIS
thd Thread handler.
RETURN
FALSE on success
TRUE on error
*/
bool
sp_rcontext::init_var_table(THD *thd)
{
List<create_field> field_def_lst;
if (!m_root_parsing_ctx->total_pvars())
return FALSE;
m_root_parsing_ctx->retrieve_field_definitions(&field_def_lst);
DBUG_ASSERT(field_def_lst.elements == m_root_parsing_ctx->total_pvars());
if (!(m_var_table= create_virtual_tmp_table(thd, field_def_lst)))
return TRUE;
m_var_table->copy_blobs= TRUE;
m_var_table->alias= "";
return FALSE;
}
/*
Create and initialize an Item-adapter (Item_field) for each SP-var field.
RETURN
FALSE on success
TRUE on error
*/
bool
sp_rcontext::init_var_items()
{
uint idx;
uint num_vars= m_root_parsing_ctx->total_pvars();
if (!(m_var_items= (Item**) sql_alloc(num_vars * sizeof (Item *))))
return TRUE;
for (idx = 0; idx < num_vars; ++idx)
{ {
res= 0; if (!(m_var_items[idx]= new Item_field(m_var_table->field[idx])))
set_item(idx, it); return TRUE;
} }
return res; return FALSE;
} }
bool
sp_rcontext::set_return_value(THD *thd, Item *return_value_item)
{
DBUG_ASSERT(m_return_value_fld);
m_return_value_set = TRUE;
return sp_eval_expr(thd, m_return_value_fld, return_value_item);
}
bool bool
sp_rcontext::find_handler(uint sql_errno, sp_rcontext::find_handler(uint sql_errno,
MYSQL_ERROR::enum_warning_level level) MYSQL_ERROR::enum_warning_level level)
@ -117,32 +213,14 @@ sp_rcontext::find_handler(uint sql_errno,
} }
if (found < 0) if (found < 0)
{ {
if (m_prev_ctx) if (m_prev_runtime_ctx)
return m_prev_ctx->find_handler(sql_errno, level); return m_prev_runtime_ctx->find_handler(sql_errno, level);
return FALSE; return FALSE;
} }
m_hfound= found; m_hfound= found;
return TRUE; return TRUE;
} }
void
sp_rcontext::save_variables(uint fp)
{
while (fp < m_count)
{
m_saved.push_front(m_frame[fp]);
m_frame[fp++]= NULL; // Prevent reuse
}
}
void
sp_rcontext::restore_variables(uint fp)
{
uint i= m_count;
while (i-- > fp)
m_frame[i]= m_saved.pop();
}
void void
sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i) sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
@ -150,6 +228,7 @@ sp_rcontext::push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i)
m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i); m_cstack[m_ccount++]= new sp_cursor(lex_keeper, i);
} }
void void
sp_rcontext::pop_cursors(uint count) sp_rcontext::pop_cursors(uint count)
{ {
@ -160,6 +239,40 @@ sp_rcontext::pop_cursors(uint count)
} }
int
sp_rcontext::set_variable(THD *thd, uint var_idx, Item *value)
{
return set_variable(thd, m_var_table->field[var_idx], value);
}
int
sp_rcontext::set_variable(THD *thd, Field *field, Item *value)
{
if (!value)
{
field->set_null();
return 0;
}
return sp_eval_expr(thd, field, value);
}
Item *
sp_rcontext::get_item(uint var_idx)
{
return m_var_items[var_idx];
}
Item **
sp_rcontext::get_item_addr(uint var_idx)
{
return m_var_items + var_idx;
}
/* /*
* *
* sp_cursor * sp_cursor
@ -263,6 +376,102 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
} }
/*
Create an instance of appropriate Item_cache class depending on the
specified type in the callers arena.
SYNOPSIS
thd thread handler
result_type type of the expression
RETURN
Pointer to valid object on success
NULL on error
NOTE
We should create cache items in the callers arena, as they are used
between in several instructions.
*/
Item_cache *
sp_rcontext::create_case_expr_holder(THD *thd, Item_result result_type)
{
Item_cache *holder;
Query_arena current_arena;
thd->set_n_backup_active_arena(thd->spcont->callers_arena, &current_arena);
holder= Item_cache::get_cache(result_type);
thd->restore_active_arena(thd->spcont->callers_arena, &current_arena);
return holder;
}
/*
Set CASE expression to the specified value.
SYNOPSIS
thd thread handler
case_expr_id identifier of the CASE expression
case_expr_item a value of the CASE expression
RETURN
FALSE on success
TRUE on error
NOTE
The idea is to reuse Item_cache for the expression of the one CASE
statement. This optimization takes place when there is CASE statement
inside of a loop. So, in other words, we will use the same object on each
iteration instead of creating a new one for each iteration.
TODO
Hypothetically, a type of CASE expression can be different for each
iteration. For instance, this can happen if the expression contains a
session variable (something like @@VAR) and its type is changed from one
iteration to another.
In order to cope with this problem, we check type each time, when we use
already created object. If the type does not match, we re-create Item.
This also can (should?) be optimized.
*/
int
sp_rcontext::set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item)
{
if (!(case_expr_item= sp_prepare_func_item(thd, &case_expr_item)))
return TRUE;
if (!m_case_expr_holders[case_expr_id] ||
m_case_expr_holders[case_expr_id]->result_type() !=
case_expr_item->result_type())
{
m_case_expr_holders[case_expr_id]=
create_case_expr_holder(thd, case_expr_item->result_type());
}
m_case_expr_holders[case_expr_id]->store(case_expr_item);
return FALSE;
}
Item *
sp_rcontext::get_case_expr(int case_expr_id)
{
return m_case_expr_holders[case_expr_id];
}
Item **
sp_rcontext::get_case_expr_addr(int case_expr_id)
{
return (Item**) m_case_expr_holders + case_expr_id;
}
/*************************************************************************** /***************************************************************************
Select_fetch_into_spvars Select_fetch_into_spvars
****************************************************************************/ ****************************************************************************/
@ -294,11 +503,8 @@ bool Select_fetch_into_spvars::send_data(List<Item> &items)
*/ */
for (; pv= pv_iter++, item= item_iter++; ) for (; pv= pv_iter++, item= item_iter++; )
{ {
Item *reuse= thd->spcont->get_item(pv->offset); if (thd->spcont->set_variable(thd, pv->offset, item))
/* Evaluate a new item on the arena of the calling instruction */ return TRUE;
Item *it= sp_eval_func_item(thd, &item, pv->type, reuse, TRUE);
thd->spcont->set_item(pv->offset, it);
} }
return FALSE; return FALSE;
} }

View file

@ -43,12 +43,22 @@ typedef struct
/* /*
This is a run context? of one SP ? This class is a runtime context of a Stored Routine. It is used in an
THis is execution and is intended to contain all dynamic objects (i.e. objects, which
- a stack of cursors? can be changed during execution), such as:
- a stack of handlers? - stored routine variables;
- a stack of Items ? - cursors;
- a stack of instruction locations in SP? - handlers;
Runtime context is used with sp_head class. sp_head class is intended to
contain all static things, related to the stored routines (code, for example).
sp_head instance creates runtime context for the execution of a stored
routine.
There is a parsing context (an instance of sp_pcontext class), which is used
on parsing stage. However, now it contains some necessary for an execution
things, such as definition of used stored routine variables. That's why
runtime context needs a reference to the parsing context.
*/ */
class sp_rcontext : public Sql_alloc class sp_rcontext : public Sql_alloc
@ -68,62 +78,34 @@ class sp_rcontext : public Sql_alloc
#ifndef DBUG_OFF #ifndef DBUG_OFF
/* /*
Routine to which this Item_splocal belongs. Used for checking if correct The routine for which this runtime context is created. Used for checking
runtime context is used for variable handling. if correct runtime context is used for variable handling.
*/ */
sp_head *owner; sp_head *sp;
#endif #endif
sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax); sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld,
sp_rcontext *prev_runtime_ctx);
bool init(THD *thd);
~sp_rcontext() ~sp_rcontext();
{
// Not needed?
//sql_element_free(m_frame);
//m_saved.empty();
}
inline void
push_item(Item *i)
{
if (m_count < m_fsize)
m_frame[m_count++]= i;
}
inline void
set_item(uint idx, Item *i)
{
if (idx < m_count)
m_frame[idx]= i;
}
/* Returns 0 on success, -1 on (eval) failure */
int int
set_item_eval(THD *thd, uint idx, Item **i, enum_field_types type); set_variable(THD *thd, uint var_idx, Item *value);
inline Item * Item *
get_item(uint idx) get_item(uint var_idx);
Item **
get_item_addr(uint var_idx);
bool
set_return_value(THD *thd, Item *return_value_item);
inline bool
is_return_value_set() const
{ {
return m_frame[idx]; return m_return_value_set;
}
inline Item **
get_item_addr(uint idx)
{
return m_frame + idx;
}
inline void
set_result(Item *it)
{
m_result= it;
}
inline Item *
get_result()
{
return m_result;
} }
inline void inline void
@ -195,14 +177,6 @@ class sp_rcontext : public Sql_alloc
m_ihsp-= 1; m_ihsp-= 1;
} }
// Save variables starting at fp and up
void
save_variables(uint fp);
// Restore variables down to fp
void
restore_variables(uint fp);
void void
push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i); push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
@ -221,13 +195,42 @@ class sp_rcontext : public Sql_alloc
return m_cstack[i]; return m_cstack[i];
} }
/*
CASE expressions support.
*/
int
set_case_expr(THD *thd, int case_expr_id, Item *case_expr_item);
Item *
get_case_expr(int case_expr_id);
Item **
get_case_expr_addr(int case_expr_id);
private: private:
sp_pcontext *m_root_parsing_ctx;
uint m_count; /* Virtual table for storing variables. */
uint m_fsize; TABLE *m_var_table;
Item **m_frame;
Item *m_result; // For FUNCTIONs /*
Collection of Item_field proxies, each of them points to the corresponding
field in m_var_table.
*/
Item **m_var_items;
/*
This is a pointer to a field, which should contain return value for stored
functions (only). For stored procedures, this pointer is NULL.
*/
Field *m_return_value_fld;
/*
Indicates whether the return value (in m_return_value_fld) has been set
during execution.
*/
bool m_return_value_set;
sp_handler_t *m_handler; // Visible handlers sp_handler_t *m_handler; // Visible handlers
uint m_hcount; // Stack pointer for m_handler uint m_hcount; // Stack pointer for m_handler
@ -236,13 +239,22 @@ private:
uint *m_in_handler; // Active handler, for recursion check uint *m_in_handler; // Active handler, for recursion check
uint m_ihsp; // Stack pointer for m_in_handler uint m_ihsp; // Stack pointer for m_in_handler
int m_hfound; // Set by find_handler; -1 if not found int m_hfound; // Set by find_handler; -1 if not found
List<Item> m_saved; // Saved variables during handler exec.
sp_cursor **m_cstack; sp_cursor **m_cstack;
uint m_ccount; uint m_ccount;
sp_rcontext *m_prev_ctx; // Previous context (NULL if none) Item_cache **m_case_expr_holders;
/* Previous runtime context (NULL if none) */
sp_rcontext *m_prev_runtime_ctx;
private:
bool init_var_table(THD *thd);
bool init_var_items();
Item_cache *create_case_expr_holder(THD *thd, Item_result result_type);
int set_variable(THD *thd, Field *field, Item *value);
}; // class sp_rcontext : public Sql_alloc }; // class sp_rcontext : public Sql_alloc

View file

@ -2760,8 +2760,9 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
uint unused_field_idx= NO_CACHED_FIELD_INDEX; uint unused_field_idx= NO_CACHED_FIELD_INDEX;
TABLE_LIST *dummy; TABLE_LIST *dummy;
Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(), Field *f=find_field_in_table_ref(thd, table_list, column->column.ptr(),
column->column.length(),
column->column.ptr(), NULL, NULL, column->column.ptr(), NULL, NULL,
column->column.length(), 0, 1, 1, 0, NULL, TRUE, FALSE,
&unused_field_idx, FALSE, &dummy); &unused_field_idx, FALSE, &dummy);
if (f == (Field*)0) if (f == (Field*)0)
{ {
@ -3616,11 +3617,28 @@ err:
} }
/*
Check column rights in given security context
SYNOPSIS
check_grant_column()
thd thread handler
grant grant information structure
db_name db name
table_name table name
name column name
length column name length
sctx security context
RETURN
FALSE OK
TRUE access denied
*/
bool check_grant_column(THD *thd, GRANT_INFO *grant, bool check_grant_column(THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
const char *name, uint length, uint show_tables) const char *name, uint length, Security_context *sctx)
{ {
Security_context *sctx= thd->security_ctx;
GRANT_TABLE *grant_table; GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column; GRANT_COLUMN *grant_column;
ulong want_access= grant->want_privilege & ~grant->privilege; ulong want_access= grant->want_privilege & ~grant->privilege;
@ -3651,31 +3669,77 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
rw_unlock(&LOCK_grant); rw_unlock(&LOCK_grant);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
#ifdef NOT_USED
if (show_tables && (grant_column || grant->privilege & COL_ACLS))
{
rw_unlock(&LOCK_grant); /* purecov: deadcode */
DBUG_RETURN(0); /* purecov: deadcode */
}
#endif
err: err:
rw_unlock(&LOCK_grant); rw_unlock(&LOCK_grant);
if (!show_tables) char command[128];
{ get_privilege_desc(command, sizeof(command), want_access);
char command[128]; my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
get_privilege_desc(command, sizeof(command), want_access); command,
my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), sctx->priv_user,
command, sctx->host_or_ip,
sctx->priv_user, name,
sctx->host_or_ip, table_name);
name,
table_name);
}
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/*
Check the access right to a column depending on the type of table.
SYNOPSIS
check_column_grant_in_table_ref()
thd thread handler
table_ref table reference where to check the field
name name of field to check
length length of name
DESCRIPTION
Check the access rights to a column depending on the type of table
reference where the column is checked. The function provides a
generic interface to check column access rights that hides the
heterogeneity of the column representation - whether it is a view
or a stored table colum.
RETURN
FALSE OK
TRUE access denied
*/
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
const char *name, uint length)
{
GRANT_INFO *grant;
const char *db_name;
const char *table_name;
Security_context *sctx= test(table_ref->security_ctx) ?
table_ref->security_ctx : thd->security_ctx;
if (table_ref->view || table_ref->field_translation)
{
/* View or derived information schema table. */
grant= &(table_ref->grant);
db_name= table_ref->view_db.str;
table_name= table_ref->view_name.str;
}
else
{
/* Normal or temporary table. */
TABLE *table= table_ref->table;
grant= &(table->grant);
db_name= table->s->db.str;
table_name= table->s->table_name.str;
}
if (grant->want_privilege)
return check_grant_column(thd, grant, db_name, table_name, name,
length, sctx);
else
return FALSE;
}
bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
const char* db_name, const char *table_name, const char* db_name, const char *table_name,
Field_iterator *fields) Field_iterator *fields)

View file

@ -205,7 +205,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
uint show_command, uint number, bool dont_print_error); uint show_command, uint number, bool dont_print_error);
bool check_grant_column (THD *thd, GRANT_INFO *grant, bool check_grant_column (THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
const char *name, uint length, uint show_command=0); const char *name, uint length, Security_context *sctx);
bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref,
const char *name, uint length);
bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
const char* db_name, const char *table_name, const char* db_name, const char *table_name,
Field_iterator *fields); Field_iterator *fields);

View file

@ -2616,15 +2616,25 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
if (!thd->prelocked_mode && !thd->lex->requires_prelocking() && if (!thd->prelocked_mode && !thd->lex->requires_prelocking() &&
thd->lex->sroutines_list.elements) thd->lex->sroutines_list.elements)
{ {
bool first_no_prelocking, need_prelocking; bool first_no_prelocking, need_prelocking, tabs_changed;
TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last; TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
DBUG_ASSERT(thd->lex->query_tables == *start); DBUG_ASSERT(thd->lex->query_tables == *start);
sp_get_prelocking_info(thd, &need_prelocking, &first_no_prelocking); sp_get_prelocking_info(thd, &need_prelocking, &first_no_prelocking);
if ((sp_cache_routines_and_add_tables(thd, thd->lex, if (sp_cache_routines_and_add_tables(thd, thd->lex,
first_no_prelocking) || first_no_prelocking,
*start) && need_prelocking) &tabs_changed))
{
/*
Serious error during reading stored routines from mysql.proc table.
Something's wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result= -1;
goto err;
}
else if ((tabs_changed || *start) && need_prelocking)
{ {
query_tables_last_own= save_query_tables_last; query_tables_last_own= save_query_tables_last;
*start= thd->lex->query_tables; *start= thd->lex->query_tables;
@ -2748,9 +2758,18 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
tables->lock_type >= TL_WRITE_ALLOW_WRITE) tables->lock_type >= TL_WRITE_ALLOW_WRITE)
{ {
if (!query_tables_last_own) if (!query_tables_last_own)
query_tables_last_own= thd->lex->query_tables_last; query_tables_last_own= thd->lex->query_tables_last;
sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex, if (sp_cache_routines_and_add_tables_for_triggers(thd, thd->lex,
tables->table->triggers); tables->table->triggers))
{
/*
Serious error during reading stored routines from mysql.proc table.
Something's wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result= -1;
goto err;
}
} }
free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC));
} }
@ -2771,9 +2790,21 @@ process_view_routines:
/* We have at least one table in TL here. */ /* We have at least one table in TL here. */
if (!query_tables_last_own) if (!query_tables_last_own)
query_tables_last_own= thd->lex->query_tables_last; query_tables_last_own= thd->lex->query_tables_last;
sp_cache_routines_and_add_tables_for_view(thd, thd->lex, tables->view); if (sp_cache_routines_and_add_tables_for_view(thd, thd->lex,
tables->view))
{
/*
Serious error during reading stored routines from mysql.proc table.
Something's wrong with the table or its contents, and an error has
been emitted; we must abort.
*/
result= -1;
goto err;
}
} }
} }
err:
thd->proc_info=0; thd->proc_info=0;
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block
@ -3337,47 +3368,6 @@ static void update_field_dependencies(THD *thd, Field *field, TABLE *table)
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check column rights in given security context
SYNOPSIS
check_grant_column_in_sctx()
thd thread handler
grant grant information structure
db db name
table table name
name column name
length column name length
check_grants need to check grants
sctx 0 or security context
RETURN
FALSE OK
TRUE access denied
*/
static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
const char *db, const char *table,
const char *name, uint length,
bool check_grants,
Security_context *sctx)
{
if (!check_grants)
return FALSE;
Security_context *save_security_ctx= thd->security_ctx;
bool res;
if (sctx)
{
thd->security_ctx= sctx;
}
res= check_grant_column(thd, grant, db, table, name, length);
thd->security_ctx= save_security_ctx;
return res;
}
#endif
/* /*
Find a field by name in a view that uses merge algorithm. Find a field by name in a view that uses merge algorithm.
@ -3386,11 +3376,10 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
thd thread handler thd thread handler
table_list view to search for 'name' table_list view to search for 'name'
name name of field name name of field
item_name name of item if it will be created (VIEW)
length length of name length length of name
item_name name of item if it will be created (VIEW)
ref expression substituted in VIEW should be passed ref expression substituted in VIEW should be passed
using this reference (return view_ref_found) using this reference (return view_ref_found)
check_grants do check columns grants for view?
register_tree_change TRUE if ref is not stack variable and we register_tree_change TRUE if ref is not stack variable and we
need register changes in item tree need register changes in item tree
@ -3402,8 +3391,8 @@ static bool check_grant_column_in_sctx(THD *thd, GRANT_INFO *grant,
static Field * static Field *
find_field_in_view(THD *thd, TABLE_LIST *table_list, find_field_in_view(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name, const char *name, uint length,
uint length, Item **ref, bool check_grants, const char *item_name, Item **ref,
bool register_tree_change) bool register_tree_change)
{ {
DBUG_ENTER("find_field_in_view"); DBUG_ENTER("find_field_in_view");
@ -3420,24 +3409,13 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
{ {
if (!my_strcasecmp(system_charset_info, field_it.name(), name)) if (!my_strcasecmp(system_charset_info, field_it.name(), name))
{ {
if (table_list->schema_table_reformed)
/*
Translation table items are always Item_fields and fixed already
('mysql_schema_table' function). So we can return ->field. It is
used only for 'show & where' commands.
*/
DBUG_RETURN(((Item_field*) (field_it.item()))->field);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grant_column_in_sctx(thd, &table_list->grant,
table_list->view_db.str,
table_list->view_name.str, name, length,
check_grants,
table_list->security_ctx))
DBUG_RETURN(WRONG_GRANT);
#endif
// in PS use own arena or data will be freed after prepare // in PS use own arena or data will be freed after prepare
if (register_tree_change) if (register_tree_change)
arena= thd->activate_stmt_arena_if_needed(&backup); arena= thd->activate_stmt_arena_if_needed(&backup);
/*
create_item() may, or may not create a new Item, depending on
the column reference. See create_view_field() for details.
*/
Item *item= field_it.create_item(thd); Item *item= field_it.create_item(thd);
if (register_tree_change && arena) if (register_tree_change && arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
@ -3479,7 +3457,6 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
length [in] length of name length [in] length of name
ref [in/out] if 'name' is resolved to a view field, ref is ref [in/out] if 'name' is resolved to a view field, ref is
set to point to the found view field set to point to the found view field
check_grants [in] do check columns grants?
register_tree_change [in] TRUE if ref is not stack variable and we register_tree_change [in] TRUE if ref is not stack variable and we
need register changes in item tree need register changes in item tree
actual_table [out] the original table reference where the field actual_table [out] the original table reference where the field
@ -3500,8 +3477,7 @@ find_field_in_view(THD *thd, TABLE_LIST *table_list,
static Field * static Field *
find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
uint length, Item **ref, bool check_grants, uint length, Item **ref, bool register_tree_change,
bool register_tree_change,
TABLE_LIST **actual_table) TABLE_LIST **actual_table)
{ {
List_iterator_fast<Natural_join_column> List_iterator_fast<Natural_join_column>
@ -3526,23 +3502,16 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
break; break;
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grants && nj_col->check_grants(thd, name, length))
DBUG_RETURN(WRONG_GRANT);
#endif
if (nj_col->view_field) if (nj_col->view_field)
{ {
Item *item; Item *item;
/*
The found field is a view field, we do as in find_field_in_view()
and return a pointer to pointer to the Item of that field.
*/
if (register_tree_change) if (register_tree_change)
arena= thd->activate_stmt_arena_if_needed(&backup); arena= thd->activate_stmt_arena_if_needed(&backup);
/*
create_item() may, or may not create a new Item, depending on the
column reference. See create_view_field() for details.
*/
item= nj_col->create_item(thd); item= nj_col->create_item(thd);
if (register_tree_change && arena) if (register_tree_change && arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
@ -3588,7 +3557,6 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
table table where to search for the field table table where to search for the field
name name of field name name of field
length length of name length length of name
check_grants do check columns grants?
allow_rowid do allow finding of "_rowid" field? allow_rowid do allow finding of "_rowid" field?
cached_field_index_ptr cached position in field list (used to speedup cached_field_index_ptr cached position in field list (used to speedup
lookup for fields in prepared tables) lookup for fields in prepared tables)
@ -3600,9 +3568,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
Field * Field *
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
bool check_grants, bool allow_rowid, bool allow_rowid, uint *cached_field_index_ptr)
uint *cached_field_index_ptr,
Security_context *sctx)
{ {
Field **field_ptr, *field; Field **field_ptr, *field;
uint cached_field_index= *cached_field_index_ptr; uint cached_field_index= *cached_field_index_ptr;
@ -3652,13 +3618,6 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
update_field_dependencies(thd, field, table); update_field_dependencies(thd, field, table);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grant_column_in_sctx(thd, &table->grant,
table->s->db.str, table->s->table_name.str,
name, length,
check_grants, sctx))
field= WRONG_GRANT;
#endif
DBUG_RETURN(field); DBUG_RETURN(field);
} }
@ -3671,14 +3630,13 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
thd [in] thread handler thd [in] thread handler
table_list [in] table reference to search table_list [in] table reference to search
name [in] name of field name [in] name of field
item_name [in] name of item if it will be created (VIEW)
table_name [in] optional table name that qualifies the field
db_name [in] optional database name that qualifies the
length [in] field length of name length [in] field length of name
item_name [in] name of item if it will be created (VIEW)
db_name [in] optional database name that qualifies the
table_name [in] optional table name that qualifies the field
ref [in/out] if 'name' is resolved to a view field, ref ref [in/out] if 'name' is resolved to a view field, ref
is set to point to the found view field is set to point to the found view field
check_grants_table [in] do check columns grants for table? check_privileges [in] check privileges
check_grants_view [in] do check columns grants for view?
allow_rowid [in] do allow finding of "_rowid" field? allow_rowid [in] do allow finding of "_rowid" field?
cached_field_index_ptr [in] cached position in field list (used to cached_field_index_ptr [in] cached position in field list (used to
speedup lookup for fields in prepared tables) speedup lookup for fields in prepared tables)
@ -3708,11 +3666,11 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length,
Field * Field *
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
const char *name, const char *item_name, const char *name, uint length,
const char *table_name, const char *db_name, const char *item_name, const char *db_name,
uint length, Item **ref, const char *table_name, Item **ref,
bool check_grants_table, bool check_grants_view, bool check_privileges, bool allow_rowid,
bool allow_rowid, uint *cached_field_index_ptr, uint *cached_field_index_ptr,
bool register_tree_change, TABLE_LIST **actual_table) bool register_tree_change, TABLE_LIST **actual_table)
{ {
Field *fld; Field *fld;
@ -3757,8 +3715,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
if (table_list->field_translation) if (table_list->field_translation)
{ {
/* 'table_list' is a view or an information schema table. */ /* 'table_list' is a view or an information schema table. */
if ((fld= find_field_in_view(thd, table_list, name, item_name, length, if ((fld= find_field_in_view(thd, table_list, name, length, item_name, ref,
ref, check_grants_view,
register_tree_change))) register_tree_change)))
*actual_table= table_list; *actual_table= table_list;
} }
@ -3767,20 +3724,9 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
/* 'table_list' is a stored table. */ /* 'table_list' is a stored table. */
DBUG_ASSERT(table_list->table); DBUG_ASSERT(table_list->table);
if ((fld= find_field_in_table(thd, table_list->table, name, length, if ((fld= find_field_in_table(thd, table_list->table, name, length,
check_grants_table, allow_rowid, allow_rowid,
cached_field_index_ptr, cached_field_index_ptr)))
table_list->security_ctx)))
*actual_table= table_list; *actual_table= table_list;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* check for views with temporary table algorithm */
if (check_grants_view && table_list->view &&
fld && fld != WRONG_GRANT &&
check_grant_column(thd, &table_list->grant,
table_list->view_db.str,
table_list->view_name.str,
name, length))
fld= WRONG_GRANT;
#endif
} }
else else
{ {
@ -3797,11 +3743,10 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
TABLE_LIST *table; TABLE_LIST *table;
while ((table= it++)) while ((table= it++))
{ {
if ((fld= find_field_in_table_ref(thd, table, name, item_name, if ((fld= find_field_in_table_ref(thd, table, name, length, item_name,
table_name, db_name, length, ref, db_name, table_name, ref,
check_grants_table, check_privileges, allow_rowid,
check_grants_view, cached_field_index_ptr,
allow_rowid, cached_field_index_ptr,
register_tree_change, actual_table))) register_tree_change, actual_table)))
DBUG_RETURN(fld); DBUG_RETURN(fld);
} }
@ -3814,11 +3759,16 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
directly the top-most NATURAL/USING join. directly the top-most NATURAL/USING join.
*/ */
fld= find_field_in_natural_join(thd, table_list, name, length, ref, fld= find_field_in_natural_join(thd, table_list, name, length, ref,
/* TIMOUR_TODO: check this with Sanja */
check_grants_table || check_grants_view,
register_tree_change, actual_table); register_tree_change, actual_table);
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check if there are sufficient access rights to the found field. */
if (fld && check_privileges &&
check_column_grant_in_table_ref(thd, *actual_table, name, length))
fld= WRONG_GRANT;
#endif
DBUG_RETURN(fld); DBUG_RETURN(fld);
} }
@ -3936,21 +3886,11 @@ find_field_in_tables(THD *thd, Item_ident *item,
*/ */
if (table_ref->table && !table_ref->view) if (table_ref->table && !table_ref->view)
found= find_field_in_table(thd, table_ref->table, name, length, found= find_field_in_table(thd, table_ref->table, name, length,
test(table_ref->table-> TRUE, &(item->cached_field_index));
grant.want_privilege) &&
check_privileges,
1, &(item->cached_field_index),
table_ref->security_ctx);
else else
found= find_field_in_table_ref(thd, table_ref, name, item->name, found= find_field_in_table_ref(thd, table_ref, name, length, item->name,
NULL, NULL, length, ref, NULL, NULL, ref, check_privileges,
(table_ref->table && TRUE, &(item->cached_field_index),
test(table_ref->table->grant.
want_privilege) &&
check_privileges),
(test(table_ref->grant.want_privilege) &&
check_privileges),
1, &(item->cached_field_index),
register_tree_change, register_tree_change,
&actual_table); &actual_table);
if (found) if (found)
@ -3990,17 +3930,9 @@ find_field_in_tables(THD *thd, Item_ident *item,
for (; cur_table != last_table ; for (; cur_table != last_table ;
cur_table= cur_table->next_name_resolution_table) cur_table= cur_table->next_name_resolution_table)
{ {
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, item->name, Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length,
table_name, db, item->name, db, table_name, ref,
length, ref, check_privileges, allow_rowid,
(cur_table->table &&
test(cur_table->table->grant.
want_privilege) &&
check_privileges),
(test(cur_table->grant.
want_privilege)
&& check_privileges),
allow_rowid,
&(item->cached_field_index), &(item->cached_field_index),
register_tree_change, register_tree_change,
&actual_table); &actual_table);
@ -4408,7 +4340,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
{ {
bool is_created_1; bool is_created_1;
bool found= FALSE; bool found= FALSE;
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created_1))) if (!(nj_col_1= it_1.get_or_create_column_ref(&is_created_1)))
goto err; goto err;
field_name_1= nj_col_1->name(); field_name_1= nj_col_1->name();
@ -4429,7 +4361,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
bool is_created_2; bool is_created_2;
Natural_join_column *cur_nj_col_2; Natural_join_column *cur_nj_col_2;
const char *cur_field_name_2; const char *cur_field_name_2;
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, &is_created_2))) if (!(cur_nj_col_2= it_2.get_or_create_column_ref(&is_created_2)))
goto err; goto err;
cur_field_name_2= cur_nj_col_2->name(); cur_field_name_2= cur_nj_col_2->name();
@ -4625,13 +4557,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
/* Append the columns of the first join operand. */ /* Append the columns of the first join operand. */
for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next()) for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next())
{ {
if (!(nj_col_1= it_1.get_or_create_column_ref(thd, &is_created))) nj_col_1= it_1.get_natural_column_ref();
goto err;
/*
The following assert checks that mark_common_columns() was run and
we created the list table_ref_1->join_columns.
*/
DBUG_ASSERT(!is_created);
if (nj_col_1->is_common) if (nj_col_1->is_common)
{ {
natural_using_join->join_columns->push_back(nj_col_1); natural_using_join->join_columns->push_back(nj_col_1);
@ -4677,13 +4603,7 @@ store_natural_using_join_columns(THD *thd, TABLE_LIST *natural_using_join,
/* Append the non-equi-join columns of the second join operand. */ /* Append the non-equi-join columns of the second join operand. */
for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next()) for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next())
{ {
if (!(nj_col_2= it_2.get_or_create_column_ref(thd, &is_created))) nj_col_2= it_2.get_natural_column_ref();
goto err;
/*
The following assert checks that mark_common_columns() was run and
we created the list table_ref_2->join_columns.
*/
DBUG_ASSERT(!is_created);
if (!nj_col_2->is_common) if (!nj_col_2->is_common)
non_join_columns->push_back(nj_col_2); non_join_columns->push_back(nj_col_2);
else else
@ -5418,8 +5338,7 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
because it was already created and stored with the natural join. because it was already created and stored with the natural join.
*/ */
Natural_join_column *nj_col; Natural_join_column *nj_col;
if (!(nj_col= field_iterator.get_or_create_column_ref(thd, if (!(nj_col= field_iterator.get_or_create_column_ref(&is_created)))
&is_created)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
DBUG_ASSERT(nj_col->table_field && !is_created); DBUG_ASSERT(nj_col->table_field && !is_created);
field_table= nj_col->table_ref->table; field_table= nj_col->table_ref->table;

View file

@ -1505,10 +1505,10 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
my_var *mv= gl++; my_var *mv= gl++;
if (mv->local) if (mv->local)
{ {
Item_splocal *var; Item_splocal *var= new Item_splocal(mv->s, mv->offset, mv->type);
(void)local_vars.push_back(var= new Item_splocal(mv->s, mv->offset)); (void)local_vars.push_back(var);
#ifndef DBUG_OFF #ifndef DBUG_OFF
var->owner= mv->owner; var->m_sp= mv->sp;
#endif #endif
} }
else else
@ -1781,8 +1781,8 @@ bool select_dumpvar::send_data(List<Item> &items)
{ {
if ((yy=var_li++)) if ((yy=var_li++))
{ {
if (thd->spcont->set_item_eval(current_thd, if (thd->spcont->set_variable(current_thd, yy->get_var_idx(),
yy->get_offset(), it.ref(), zz->type)) *it.ref()))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
} }

View file

@ -2111,7 +2111,7 @@ public:
Routine to which this Item_splocal belongs. Used for checking if correct Routine to which this Item_splocal belongs. Used for checking if correct
runtime context is used for variable handling. runtime context is used for variable handling.
*/ */
sp_head *owner; sp_head *sp;
#endif #endif
bool local; bool local;
uint offset; uint offset;

View file

@ -113,11 +113,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
{ // Part field list { // Part field list
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
Name_resolution_context *context= &select_lex->context; Name_resolution_context *context= &select_lex->context;
TABLE_LIST *save_next_local; Name_resolution_context_state ctx_state;
TABLE_LIST *save_table_list;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
int res; int res;
if (fields.elements != values.elements) if (fields.elements != values.elements)
@ -130,14 +126,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
select_lex->no_wrap_view_item= TRUE; select_lex->no_wrap_view_item= TRUE;
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
save_table_list= context->table_list; ctx_state.save_state(context, table_list);
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
/* /*
Perform name resolution only in the first table - 'table_list', Perform name resolution only in the first table - 'table_list',
@ -152,13 +141,7 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list,
res= setup_fields(thd, 0, fields, 2, 0, 0); res= setup_fields(thd, 0, fields, 2, 0, 0);
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
thd->lex->select_lex.no_wrap_view_item= FALSE; thd->lex->select_lex.no_wrap_view_item= FALSE;
if (res) if (res)
@ -293,13 +276,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
ulonglong id; ulonglong id;
COPY_INFO info; COPY_INFO info;
TABLE *table= 0; TABLE *table= 0;
TABLE_LIST *save_table_list;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
List_iterator_fast<List_item> its(values_list); List_iterator_fast<List_item> its(values_list);
List_item *values; List_item *values;
Name_resolution_context *context; Name_resolution_context *context;
Name_resolution_context_state ctx_state;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
char *query= thd->query; char *query= thd->query;
#endif #endif
@ -380,13 +360,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
context= &thd->lex->select_lex.context; context= &thd->lex->select_lex.context;
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
save_table_list= context->table_list; ctx_state.save_state(context, table_list);
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_next_local= table_list->next_local;
/* /*
Perform name resolution only in the first table - 'table_list', Perform name resolution only in the first table - 'table_list',
@ -410,16 +384,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
its.rewind (); its.rewind ();
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
/* /*
Fill in the given fields and dump it to the table file Fill in the given fields and dump it to the table file
*/ */
info.records= info.deleted= info.copied= info.updated= 0; info.records= info.deleted= info.copied= info.updated= 0;
info.ignore= ignore; info.ignore= ignore;
info.handle_duplicates=duplic; info.handle_duplicates=duplic;
@ -827,11 +796,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
{ {
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
Name_resolution_context *context= &select_lex->context; Name_resolution_context *context= &select_lex->context;
TABLE_LIST *save_table_list; Name_resolution_context_state ctx_state;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table;
TABLE_LIST *save_next_name_resolution_table;
bool save_resolve_in_select_list;
bool insert_into_view= (table_list->view != 0); bool insert_into_view= (table_list->view != 0);
bool res= 0; bool res= 0;
DBUG_ENTER("mysql_prepare_insert"); DBUG_ENTER("mysql_prepare_insert");
@ -871,15 +836,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
save_table_list= context->table_list; ctx_state.save_state(context, table_list);
/* Here first_name_resolution_table points to the first select table. */
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_resolve_in_select_list= context->resolve_in_select_list;
save_next_local= table_list->next_local;
/* /*
Perform name resolution only in the first table - 'table_list', Perform name resolution only in the first table - 'table_list',
@ -904,23 +861,17 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list,
*/ */
if (select_lex->group_list.elements == 0) if (select_lex->group_list.elements == 0)
{ {
context->table_list->next_local= save_next_local; context->table_list->next_local= ctx_state.save_next_local;
/* first_name_resolution_table was set by resolve_in_table_list_only() */ /* first_name_resolution_table was set by resolve_in_table_list_only() */
context->first_name_resolution_table-> context->first_name_resolution_table->
next_name_resolution_table= save_next_local; next_name_resolution_table= ctx_state.save_next_local;
} }
if (!res) if (!res)
res= setup_fields(thd, 0, update_values, 1, 0, 0); res= setup_fields(thd, 0, update_values, 1, 0, 0);
} }
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->table_list= save_table_list;
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
context->resolve_in_select_list= save_resolve_in_select_list;
if (res) if (res)
DBUG_RETURN(res); DBUG_RETURN(res);
@ -2187,17 +2138,10 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{ {
/* Save the state of the current name resolution context. */ /* Save the state of the current name resolution context. */
Name_resolution_context *context= &lex->select_lex.context; Name_resolution_context *context= &lex->select_lex.context;
TABLE_LIST *save_table_list; Name_resolution_context_state ctx_state;
TABLE_LIST *save_next_local;
TABLE_LIST *save_first_name_resolution_table; /* Save the state of the current name resolution context. */
TABLE_LIST *save_next_name_resolution_table; ctx_state.save_state(context, table_list);
save_table_list= context->table_list;
save_first_name_resolution_table= context->first_name_resolution_table;
save_next_name_resolution_table= (context->first_name_resolution_table) ?
context->first_name_resolution_table->
next_name_resolution_table :
NULL;
save_next_local= table_list->next_local;
/* Perform name resolution only in the first table - 'table_list'. */ /* Perform name resolution only in the first table - 'table_list'. */
table_list->next_local= 0; table_list->next_local= 0;
@ -2213,20 +2157,15 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
*/ */
if (lex->select_lex.group_list.elements == 0) if (lex->select_lex.group_list.elements == 0)
{ {
context->table_list->next_local= save_next_local; context->table_list->next_local= ctx_state.save_next_local;
/* first_name_resolution_table was set by resolve_in_table_list_only() */ /* first_name_resolution_table was set by resolve_in_table_list_only() */
context->first_name_resolution_table-> context->first_name_resolution_table->
next_name_resolution_table= save_next_local; next_name_resolution_table= ctx_state.save_next_local;
} }
res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0); res= res || setup_fields(thd, 0, *info.update_values, 1, 0, 0);
/* Restore the current context. */ /* Restore the current context. */
table_list->next_local= save_next_local; ctx_state.restore_state(context, table_list);
context->first_name_resolution_table= save_first_name_resolution_table;
if (context->first_name_resolution_table)
context->first_name_resolution_table->
next_name_resolution_table= save_next_name_resolution_table;
} }
lex->current_select= lex_current_select_save; lex->current_select= lex_current_select_save;

View file

@ -1130,6 +1130,11 @@ void st_select_lex::init_query()
/* /*
Add the name resolution context of the current (sub)query to the Add the name resolution context of the current (sub)query to the
stack of contexts for the whole query. stack of contexts for the whole query.
TODO:
push_context may return an error if there is no memory for a new
element in the stack, however this method has no return value,
thus push_context should be moved to a place where query
initialization is checked for failure.
*/ */
parent_lex->push_context(&context); parent_lex->push_context(&context);
cond_count= with_wild= 0; cond_count= with_wild= 0;

View file

@ -1024,9 +1024,9 @@ typedef struct st_lex
} }
void cleanup_after_one_table_open(); void cleanup_after_one_table_open();
void push_context(Name_resolution_context *context) bool push_context(Name_resolution_context *context)
{ {
context_stack.push_front(context); return context_stack.push_front(context);
} }
void pop_context() void pop_context()

View file

@ -266,10 +266,21 @@ protected:
ls.elements= elm; ls.elements= elm;
} }
public: public:
base_list_iterator(base_list &list_par) base_list_iterator()
:list(&list_par), el(&list_par.first), prev(0), current(0) :list(0), el(0), prev(0), current(0)
{} {}
base_list_iterator(base_list &list_par)
{ init(list_par); }
inline void init(base_list &list_par)
{
list= &list_par;
el= &list_par.first;
prev= 0;
current= 0;
}
inline void *next(void) inline void *next(void)
{ {
prev=el; prev=el;
@ -364,6 +375,8 @@ template <class T> class List_iterator :public base_list_iterator
{ {
public: public:
List_iterator(List<T> &a) : base_list_iterator(a) {} List_iterator(List<T> &a) : base_list_iterator(a) {}
List_iterator() : base_list_iterator() {}
inline void init(List<T> &a) { base_list_iterator::init(a); }
inline T* operator++(int) { return (T*) base_list_iterator::next(); } inline T* operator++(int) { return (T*) base_list_iterator::next(); }
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); } inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); } inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
@ -385,6 +398,8 @@ protected:
public: public:
inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {} inline List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline List_iterator_fast() : base_list_iterator() {}
inline void init(List<T> &a) { base_list_iterator::init(a); }
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); } inline void rewind(void) { base_list_iterator::rewind(); }
void sublist(List<T> &list_arg, uint el_arg) void sublist(List<T> &list_arg, uint el_arg)

View file

@ -2614,7 +2614,8 @@ mysql_execute_command(THD *thd)
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements; thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_backup_table(thd, first_table); res = mysql_backup_table(thd, first_table);
select_lex->table_list.first= (byte*) first_table;
lex->query_tables=all_tables;
break; break;
} }
case SQLCOM_RESTORE_TABLE: case SQLCOM_RESTORE_TABLE:
@ -2626,6 +2627,8 @@ mysql_execute_command(THD *thd)
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements; thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_restore_table(thd, first_table); res = mysql_restore_table(thd, first_table);
select_lex->table_list.first= (byte*) first_table;
lex->query_tables=all_tables;
break; break;
} }
case SQLCOM_ASSIGN_TO_KEYCACHE: case SQLCOM_ASSIGN_TO_KEYCACHE:
@ -3119,6 +3122,8 @@ end_with_restore_list:
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
} }
select_lex->table_list.first= (byte*) first_table;
lex->query_tables=all_tables;
break; break;
} }
case SQLCOM_CHECK: case SQLCOM_CHECK:
@ -3129,6 +3134,8 @@ end_with_restore_list:
goto error; /* purecov: inspected */ goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements; thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_check_table(thd, first_table, &lex->check_opt); res = mysql_check_table(thd, first_table, &lex->check_opt);
select_lex->table_list.first= (byte*) first_table;
lex->query_tables=all_tables;
break; break;
} }
case SQLCOM_ANALYZE: case SQLCOM_ANALYZE:
@ -3149,6 +3156,8 @@ end_with_restore_list:
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
} }
select_lex->table_list.first= (byte*) first_table;
lex->query_tables=all_tables;
break; break;
} }
@ -3172,6 +3181,8 @@ end_with_restore_list:
mysql_bin_log.write(&qinfo); mysql_bin_log.write(&qinfo);
} }
} }
select_lex->table_list.first= (byte*) first_table;
lex->query_tables=all_tables;
break; break;
} }
case SQLCOM_UPDATE: case SQLCOM_UPDATE:
@ -4122,14 +4133,6 @@ end_with_restore_list:
} }
} }
#endif #endif
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
!(lex->sphead->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
}
/* /*
We need to copy name and db in order to use them for We need to copy name and db in order to use them for
@ -5765,9 +5768,10 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
buf, "TIMESTAMP"); buf, "TIMESTAMP");
} }
if (!(new_field= new_create_field(thd, field_name, type, length, decimals, if (!(new_field= new create_field()) ||
type_modifier, default_value, on_update_value, new_field->init(thd, field_name, type, length, decimals, type_modifier,
comment, change, interval_list, cs, uint_geom_type))) default_value, on_update_value, comment, change,
interval_list, cs, uint_geom_type))
DBUG_RETURN(1); DBUG_RETURN(1);
lex->create_list.push_back(new_field); lex->create_list.push_back(new_field);
@ -5775,327 +5779,6 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*****************************************************************************
** Create field definition for create
** Return 0 on failure, otherwise return create_field instance
******************************************************************************/
create_field *
new_create_field(THD *thd, char *field_name, enum_field_types type,
char *length, char *decimals,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
char *change, List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type)
{
register create_field *new_field;
uint sign_len, allowed_type_modifier=0;
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("new_create_field");
if (!(new_field=new create_field()))
DBUG_RETURN(NULL);
new_field->field=0;
new_field->field_name=field_name;
new_field->def= default_value;
new_field->flags= type_modifier;
new_field->unireg_check= (type_modifier & AUTO_INCREMENT_FLAG ?
Field::NEXT_NUMBER : Field::NONE);
new_field->decimals= decimals ? (uint)atoi(decimals) : 0;
if (new_field->decimals >= NOT_FIXED_DEC)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), new_field->decimals, field_name,
NOT_FIXED_DEC-1);
DBUG_RETURN(NULL);
}
new_field->sql_type=type;
new_field->length=0;
new_field->change=change;
new_field->interval=0;
new_field->pack_length= new_field->key_length= 0;
new_field->charset=cs;
new_field->geom_type= (Field::geometry_type) uint_geom_type;
new_field->comment=*comment;
/*
Set flag if this field doesn't have a default value
*/
if (!default_value && !(type_modifier & AUTO_INCREMENT_FLAG) &&
(type_modifier & NOT_NULL_FLAG) && type != FIELD_TYPE_TIMESTAMP)
new_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (length && !(new_field->length= (uint) atoi(length)))
length=0; /* purecov: inspected */
sign_len=type_modifier & UNSIGNED_FLAG ? 0 : 1;
switch (type) {
case FIELD_TYPE_TINY:
if (!length) new_field->length=MAX_TINYINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_SHORT:
if (!length) new_field->length=MAX_SMALLINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_INT24:
if (!length) new_field->length=MAX_MEDIUMINT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_LONG:
if (!length) new_field->length=MAX_INT_WIDTH+sign_len;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_LONGLONG:
if (!length) new_field->length=MAX_BIGINT_WIDTH;
allowed_type_modifier= AUTO_INCREMENT_FLAG;
break;
case FIELD_TYPE_NULL:
break;
case FIELD_TYPE_NEWDECIMAL:
if (!length && !new_field->decimals)
new_field->length= 10;
if (new_field->length > DECIMAL_MAX_PRECISION)
{
my_error(ER_TOO_BIG_PRECISION, MYF(0), new_field->length, field_name,
DECIMAL_MAX_PRECISION);
DBUG_RETURN(NULL);
}
if (new_field->length < new_field->decimals)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(NULL);
}
new_field->length=
my_decimal_precision_to_length(new_field->length, new_field->decimals,
type_modifier & UNSIGNED_FLAG);
new_field->pack_length=
my_decimal_get_binary_size(new_field->length, new_field->decimals);
break;
case MYSQL_TYPE_VARCHAR:
/*
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
if they don't have a default value
*/
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
break;
case MYSQL_TYPE_STRING:
break;
case FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_GEOMETRY:
if (default_value) // Allow empty as default value
{
String str,*res;
res=default_value->val_str(&str);
if (res->length())
{
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
field_name); /* purecov: inspected */
DBUG_RETURN(NULL);
}
new_field->def=0;
}
new_field->flags|=BLOB_FLAG;
break;
case FIELD_TYPE_YEAR:
if (!length || new_field->length != 2)
new_field->length=4; // Default length
new_field->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
break;
case FIELD_TYPE_FLOAT:
/* change FLOAT(precision) to FLOAT or DOUBLE */
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (length && !decimals)
{
uint tmp_length=new_field->length;
if (tmp_length > PRECISION_FOR_DOUBLE)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(NULL);
}
else if (tmp_length > PRECISION_FOR_FLOAT)
{
new_field->sql_type=FIELD_TYPE_DOUBLE;
new_field->length=DBL_DIG+7; // -[digits].E+###
}
else
new_field->length=FLT_DIG+6; // -[digits].E+##
new_field->decimals= NOT_FIXED_DEC;
break;
}
if (!length && !decimals)
{
new_field->length = FLT_DIG+6;
new_field->decimals= NOT_FIXED_DEC;
}
if (new_field->length < new_field->decimals &&
new_field->decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(NULL);
}
break;
case FIELD_TYPE_DOUBLE:
allowed_type_modifier= AUTO_INCREMENT_FLAG;
if (!length && !decimals)
{
new_field->length = DBL_DIG+7;
new_field->decimals=NOT_FIXED_DEC;
}
if (new_field->length < new_field->decimals &&
new_field->decimals != NOT_FIXED_DEC)
{
my_error(ER_M_BIGGER_THAN_D, MYF(0), field_name);
DBUG_RETURN(NULL);
}
break;
case FIELD_TYPE_TIMESTAMP:
if (!length)
new_field->length= 14; // Full date YYYYMMDDHHMMSS
else if (new_field->length != 19)
{
/*
We support only even TIMESTAMP lengths less or equal than 14
and 19 as length of 4.1 compatible representation.
*/
new_field->length=((new_field->length+1)/2)*2; /* purecov: inspected */
new_field->length= min(new_field->length,14); /* purecov: inspected */
}
new_field->flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
if (default_value)
{
/* Grammar allows only NOW() value for ON UPDATE clause */
if (default_value->type() == Item::FUNC_ITEM &&
((Item_func*)default_value)->functype() == Item_func::NOW_FUNC)
{
new_field->unireg_check= (on_update_value?Field::TIMESTAMP_DNUN_FIELD:
Field::TIMESTAMP_DN_FIELD);
/*
We don't need default value any longer moreover it is dangerous.
Everything handled by unireg_check further.
*/
new_field->def= 0;
}
else
new_field->unireg_check= (on_update_value?Field::TIMESTAMP_UN_FIELD:
Field::NONE);
}
else
{
/*
If we have default TIMESTAMP NOT NULL column without explicit DEFAULT
or ON UPDATE values then for the sake of compatiblity we should treat
this column as having DEFAULT NOW() ON UPDATE NOW() (when we don't
have another TIMESTAMP column with auto-set option before this one)
or DEFAULT 0 (in other cases).
So here we are setting TIMESTAMP_OLD_FIELD only temporary, and will
replace this value by TIMESTAMP_DNUN_FIELD or NONE later when
information about all TIMESTAMP fields in table will be availiable.
If we have TIMESTAMP NULL column without explicit DEFAULT value
we treat it as having DEFAULT NULL attribute.
*/
new_field->unireg_check= (on_update_value ?
Field::TIMESTAMP_UN_FIELD :
(new_field->flags & NOT_NULL_FLAG ?
Field::TIMESTAMP_OLD_FIELD:
Field::NONE));
}
break;
case FIELD_TYPE_DATE: // Old date type
if (protocol_version != PROTOCOL_VERSION-1)
new_field->sql_type=FIELD_TYPE_NEWDATE;
/* fall trough */
case FIELD_TYPE_NEWDATE:
new_field->length=10;
break;
case FIELD_TYPE_TIME:
new_field->length=10;
break;
case FIELD_TYPE_DATETIME:
new_field->length=19;
break;
case FIELD_TYPE_SET:
{
if (interval_list->elements > sizeof(longlong)*8)
{
my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
DBUG_RETURN(NULL);
}
new_field->pack_length= get_set_pack_length(interval_list->elements);
List_iterator<String> it(*interval_list);
String *tmp;
while ((tmp= it++))
new_field->interval_list.push_back(tmp);
/*
Set fake length to 1 to pass the below conditions.
Real length will be set in mysql_prepare_table()
when we know the character set of the column
*/
new_field->length= 1;
break;
}
case FIELD_TYPE_ENUM:
{
// Should be safe
new_field->pack_length= get_enum_pack_length(interval_list->elements);
List_iterator<String> it(*interval_list);
String *tmp;
while ((tmp= it++))
new_field->interval_list.push_back(tmp);
new_field->length= 1; // See comment for FIELD_TYPE_SET above.
break;
}
case MYSQL_TYPE_VAR_STRING:
DBUG_ASSERT(0); // Impossible
break;
case MYSQL_TYPE_BIT:
{
if (!length)
new_field->length= 1;
if (new_field->length > MAX_BIT_FIELD_LENGTH)
{
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name,
MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(NULL);
}
new_field->pack_length= (new_field->length + 7) / 8;
break;
}
case FIELD_TYPE_DECIMAL:
DBUG_ASSERT(0); /* Was obsolete */
}
if (!(new_field->flags & BLOB_FLAG) &&
((new_field->length > max_field_charlength && type != FIELD_TYPE_SET &&
type != FIELD_TYPE_ENUM &&
(type != MYSQL_TYPE_VARCHAR || default_value)) ||
(!new_field->length &&
type != MYSQL_TYPE_STRING &&
type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY)))
{
my_error((type == MYSQL_TYPE_VAR_STRING || type == MYSQL_TYPE_VARCHAR ||
type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
ER_TOO_BIG_DISPLAYWIDTH,
MYF(0),
field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(NULL);
}
type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier)
{
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(NULL);
}
DBUG_RETURN(new_field);
}
/* Store position for column in ALTER TABLE .. ADD column */ /* Store position for column in ALTER TABLE .. ADD column */
@ -6593,36 +6276,39 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
/* /*
Create a new name resolution context for a JOIN ... ON clause. Push a new name resolution context for a JOIN ... ON clause to the
context stack of a query block.
SYNOPSIS SYNOPSIS
make_join_on_context() push_new_name_resolution_context()
thd pointer to current thread thd pointer to current thread
left_op left operand of the JOIN left_op left operand of the JOIN
right_op rigth operand of the JOIN right_op rigth operand of the JOIN
DESCRIPTION DESCRIPTION
Create a new name resolution context for a JOIN ... ON clause, Create a new name resolution context for a JOIN ... ON clause,
and set the first and last leaves of the list of table references set the first and last leaves of the list of table references
to be used for name resolution. to be used for name resolution, and push the newly created
context to the stack of contexts of the query.
RETURN RETURN
A new context if all is OK FALSE if all is OK
NULL - if a memory allocation error occured TRUE if a memory allocation error occured
*/ */
Name_resolution_context * bool
make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op) push_new_name_resolution_context(THD *thd,
TABLE_LIST *left_op, TABLE_LIST *right_op)
{ {
Name_resolution_context *on_context; Name_resolution_context *on_context;
if (!(on_context= new (thd->mem_root) Name_resolution_context)) if (!(on_context= new (thd->mem_root) Name_resolution_context))
return NULL; return TRUE;
on_context->init(); on_context->init();
on_context->first_name_resolution_table= on_context->first_name_resolution_table=
left_op->first_leaf_for_name_resolution(); left_op->first_leaf_for_name_resolution();
on_context->last_name_resolution_table= on_context->last_name_resolution_table=
right_op->last_leaf_for_name_resolution(); right_op->last_leaf_for_name_resolution();
return on_context; return thd->lex->push_context(on_context);
} }

View file

@ -8951,6 +8951,7 @@ err:
TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list) TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
{ {
uint field_count= field_list.elements; uint field_count= field_list.elements;
uint blob_count= 0;
Field **field; Field **field;
create_field *cdef; /* column definition */ create_field *cdef; /* column definition */
uint record_length= 0; uint record_length= 0;
@ -8967,6 +8968,12 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
table->s= share= (TABLE_SHARE*) (table+1); table->s= share= (TABLE_SHARE*) (table+1);
share->fields= field_count; share->fields= field_count;
if (!(share->blob_field= (uint*)thd->alloc((field_list.elements + 1) *
sizeof(uint))))
return 0;
share->blob_ptr_size= mi_portable_sizeof_char_ptr;
/* Create all fields and calculate the total length of record */ /* Create all fields and calculate the total length of record */
List_iterator_fast<create_field> it(field_list); List_iterator_fast<create_field> it(field_list);
while ((cdef= it++)) while ((cdef= it++))
@ -8983,9 +8990,15 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
record_length+= (*field)->pack_length(); record_length+= (*field)->pack_length();
if (! ((*field)->flags & NOT_NULL_FLAG)) if (! ((*field)->flags & NOT_NULL_FLAG))
null_count++; null_count++;
if ((*field)->flags & BLOB_FLAG)
share->blob_field[blob_count++]= (uint) (field - table->field);
field++; field++;
} }
*field= NULL; /* mark the end of the list */ *field= NULL; /* mark the end of the list */
share->blob_field[blob_count]= 0; /* mark the end of the list */
share->blob_fields= blob_count;
null_pack_length= (null_count + 7)/8; null_pack_length= (null_count + 7)/8;
share->reclength= record_length + null_pack_length; share->reclength= record_length + null_pack_length;

View file

@ -407,7 +407,6 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields, ORDER *group, bool distinct, bool save_sum_fields,
ulonglong select_options, ha_rows rows_limit, ulonglong select_options, ha_rows rows_limit,
char* alias); char* alias);
TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list);
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func); bool reset_with_sum_func);

View file

@ -2412,18 +2412,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
*/ */
lex->query_tables= table; lex->query_tables= table;
lex->query_tables_last= &table->next_global; lex->query_tables_last= &table->next_global;
lex->query_tables_own_last= 0;; lex->query_tables_own_last= 0;
thd->no_warnings_for_error= no_warnings_for_error; thd->no_warnings_for_error= no_warnings_for_error;
if (view_operator_func == NULL)
table->required_type=FRMTYPE_TABLE;
open_and_lock_tables(thd, table); open_and_lock_tables(thd, table);
thd->no_warnings_for_error= 0; thd->no_warnings_for_error= 0;
table->next_global= save_next_global; table->next_global= save_next_global;
table->next_local= save_next_local; table->next_local= save_next_local;
/* if view are unsupported */
if (table->view && view_operator_func == NULL)
{
result_code= HA_ADMIN_NOT_BASE_TABLE;
goto send_result;
}
thd->open_options&= ~extra_open_options; thd->open_options&= ~extra_open_options;
if (prepare_func) if (prepare_func)

View file

@ -1123,7 +1123,7 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
trg_action_time_type time_type, trg_action_time_type time_type,
bool old_row_is_record1) bool old_row_is_record1)
{ {
int res= 0; bool err_status= FALSE;
sp_head *sp_trigger= bodies[event][time_type]; sp_head *sp_trigger= bodies[event][time_type];
if (sp_trigger) if (sp_trigger)
@ -1183,7 +1183,7 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
#endif // NO_EMBEDDED_ACCESS_CHECKS #endif // NO_EMBEDDED_ACCESS_CHECKS
thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER); thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
res= sp_trigger->execute_function(thd, 0, 0, 0); err_status= sp_trigger->execute_function(thd, 0, 0, 0);
thd->restore_sub_statement_state(&statement_state); thd->restore_sub_statement_state(&statement_state);
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
@ -1191,7 +1191,7 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
#endif // NO_EMBEDDED_ACCESS_CHECKS #endif // NO_EMBEDDED_ACCESS_CHECKS
} }
return res; return err_status;
} }

View file

@ -117,7 +117,7 @@ public:
void set_table(TABLE *new_table); void set_table(TABLE *new_table);
friend class Item_trigger_field; friend class Item_trigger_field;
friend void sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex, friend int sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
Table_triggers_list *triggers); Table_triggers_list *triggers);
private: private:

View file

@ -1377,41 +1377,11 @@ create_function_tail:
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
LEX_STRING cmt = { 0, 0 };
create_field *new_field;
uint unused1= 0;
int unused2= 0;
if (!(new_field= new_create_field(YYTHD, (char*) "", if (sp->fill_field_definition(YYTHD, lex,
(enum enum_field_types)$8, (enum enum_field_types) $8,
lex->length, lex->dec, lex->type, &sp->m_return_field_def))
(Item *)0, (Item *) 0, &cmt, 0, YYABORT;
&lex->interval_list,
(lex->charset ? lex->charset :
default_charset_info),
lex->uint_geom_type)))
YYABORT;
sp->m_returns_cs= new_field->charset;
if (new_field->interval_list.elements)
{
new_field->interval=
sp->create_typelib(&new_field->interval_list);
}
sp_prepare_create_field(YYTHD, new_field);
if (prepare_create_field(new_field, &unused1, &unused2, &unused2,
HA_CAN_GEOMETRY))
YYABORT;
sp->m_returns= new_field->sql_type;
sp->m_returns_cs= new_field->charset;
sp->m_returns_len= new_field->length;
sp->m_returns_pack= new_field->pack_flag;
sp->m_returns_typelib= new_field->interval;
sp->m_geom_returns= new_field->geom_type;
new_field->interval= NULL;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
@ -1434,6 +1404,11 @@ create_function_tail:
YYABORT; YYABORT;
lex->sql_command= SQLCOM_CREATE_SPFUNCTION; lex->sql_command= SQLCOM_CREATE_SPFUNCTION;
sp->init_strings(YYTHD, lex, lex->spname); sp->init_strings(YYTHD, lex, lex->spname);
if (!(sp->m_flags & sp_head::HAS_RETURN))
{
my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str);
YYABORT;
}
/* Restore flag if it was cleared above */ /* Restore flag if it was cleared above */
if (sp->m_old_cmq) if (sp->m_old_cmq)
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES; YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
@ -1528,8 +1503,28 @@ sp_fdparams:
| sp_fdparam | sp_fdparam
; ;
sp_init_param:
/* Empty */
{
LEX *lex= Lex;
lex->length= 0;
lex->dec= 0;
lex->type= 0;
lex->default_value= 0;
lex->on_update_value= 0;
lex->comment= null_lex_str;
lex->charset= NULL;
lex->interval_list.empty();
lex->uint_geom_type= 0;
}
;
sp_fdparam: sp_fdparam:
ident type ident sp_init_param type
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_pcontext *spc= lex->spcont; sp_pcontext *spc= lex->spcont;
@ -1539,7 +1534,17 @@ sp_fdparam:
my_error(ER_SP_DUP_PARAM, MYF(0), $1.str); my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
YYABORT; YYABORT;
} }
spc->push_pvar(&$1, (enum enum_field_types)$2, sp_param_in); sp_pvar_t *pvar= spc->push_pvar(&$1, (enum enum_field_types)$3,
sp_param_in);
if (lex->sphead->fill_field_definition(YYTHD, lex,
(enum enum_field_types) $3,
&pvar->field_def))
{
YYABORT;
}
pvar->field_def.field_name= pvar->name.str;
pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
} }
; ;
@ -1555,18 +1560,27 @@ sp_pdparams:
; ;
sp_pdparam: sp_pdparam:
sp_opt_inout ident type sp_opt_inout sp_init_param ident type
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_pcontext *spc= lex->spcont; sp_pcontext *spc= lex->spcont;
if (spc->find_pvar(&$2, TRUE)) if (spc->find_pvar(&$3, TRUE))
{ {
my_error(ER_SP_DUP_PARAM, MYF(0), $2.str); my_error(ER_SP_DUP_PARAM, MYF(0), $3.str);
YYABORT; YYABORT;
} }
spc->push_pvar(&$2, (enum enum_field_types)$3, sp_pvar_t *pvar= spc->push_pvar(&$3, (enum enum_field_types)$4,
(sp_param_mode_t)$1); (sp_param_mode_t)$1);
if (lex->sphead->fill_field_definition(YYTHD, lex,
(enum enum_field_types) $4,
&pvar->field_def))
{
YYABORT;
}
pvar->field_def.field_name= pvar->name.str;
pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
} }
; ;
@ -1618,45 +1632,60 @@ sp_decls:
; ;
sp_decl: sp_decl:
DECLARE_SYM sp_decl_idents type DECLARE_SYM sp_decl_idents
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sphead->reset_lex(YYTHD); lex->sphead->reset_lex(YYTHD);
lex->spcont->declare_var_boundary($2); lex->spcont->declare_var_boundary($2);
} }
type
sp_opt_default sp_opt_default
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_pcontext *ctx= lex->spcont; sp_pcontext *pctx= lex->spcont;
uint max= ctx->context_pvars(); uint num_vars= pctx->context_pvars();
enum enum_field_types type= (enum enum_field_types)$3; enum enum_field_types var_type= (enum enum_field_types) $4;
Item *it= $5; Item *dflt_value_item= $5;
bool has_default= (it != NULL); create_field *create_field_op;
for (uint i = max-$2 ; i < max ; i++) if (!dflt_value_item)
{ {
sp_instr_set *in; dflt_value_item= new Item_null();
uint off= ctx->pvar_context2index(i); /* QQ Set to the var_type with null_value? */
ctx->set_type(off, type);
if (! has_default)
it= new Item_null(); /* QQ Set to the type with null_value? */
in = new sp_instr_set(lex->sphead->instructions(),
ctx,
off,
it, type, lex,
(i == max - 1));
/*
The last instruction is assigned to be responsible for
freeing LEX.
*/
lex->sphead->add_instr(in);
ctx->set_default(off, it);
} }
ctx->declare_var_boundary(0);
for (uint i = num_vars-$2 ; i < num_vars ; i++)
{
uint var_idx= pctx->pvar_context2index(i);
sp_pvar_t *pvar= pctx->find_pvar(var_idx);
if (!pvar)
YYABORT;
pvar->type= var_type;
pvar->dflt= dflt_value_item;
if (lex->sphead->fill_field_definition(YYTHD, lex, var_type,
&pvar->field_def))
{
YYABORT;
}
pvar->field_def.field_name= pvar->name.str;
pvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL;
/* The last instruction is responsible for freeing LEX. */
lex->sphead->add_instr(
new sp_instr_set(lex->sphead->instructions(), pctx, var_idx,
dflt_value_item, var_type, lex,
(i == num_vars - 1)));
}
pctx->declare_var_boundary(0);
lex->sphead->restore_lex(YYTHD); lex->sphead->restore_lex(YYTHD);
$$.vars= $2; $$.vars= $2;
$$.conds= $$.hndlrs= $$.curs= 0; $$.conds= $$.hndlrs= $$.curs= 0;
} }
@ -1879,6 +1908,8 @@ sp_hcond:
sp_decl_idents: sp_decl_idents:
ident ident
{ {
/* NOTE: field definition is filled in sp_decl section. */
LEX *lex= Lex; LEX *lex= Lex;
sp_pcontext *spc= lex->spcont; sp_pcontext *spc= lex->spcont;
@ -1892,6 +1923,8 @@ sp_decl_idents:
} }
| sp_decl_idents ',' ident | sp_decl_idents ',' ident
{ {
/* NOTE: field definition is filled in sp_decl section. */
LEX *lex= Lex; LEX *lex= Lex;
sp_pcontext *spc= lex->spcont; sp_pcontext *spc= lex->spcont;
@ -1969,8 +2002,8 @@ sp_proc_stmt:
{ {
sp_instr_freturn *i; sp_instr_freturn *i;
i= new sp_instr_freturn(sp->instructions(), lex->spcont, i= new sp_instr_freturn(sp->instructions(), lex->spcont, $3,
$3, sp->m_returns, lex); sp->m_return_field_def.sql_type, lex);
sp->add_instr(i); sp->add_instr(i);
sp->m_flags|= sp_head::HAS_RETURN; sp->m_flags|= sp_head::HAS_RETURN;
} }
@ -1986,25 +2019,27 @@ sp_proc_stmt:
{ Lex->sphead->reset_lex(YYTHD); } { Lex->sphead->reset_lex(YYTHD); }
expr WHEN_SYM expr WHEN_SYM
{ {
/* We "fake" this by using an anonymous variable which we
set to the expression. Note that all WHENs are evaluate
at the same frame level, so we then know that it's the
top-most variable in the frame. */
LEX *lex= Lex; LEX *lex= Lex;
uint offset= lex->spcont->current_pvars(); sp_head *sp= lex->sphead;
sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(), sp_pcontext *parsing_ctx= lex->spcont;
lex->spcont, offset, $3, int case_expr_id= parsing_ctx->register_case_expr();
MYSQL_TYPE_STRING, lex, TRUE);
LEX_STRING dummy={(char*)"", 0}; if (parsing_ctx->push_case_expr_id(case_expr_id))
YYABORT;
lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in);
lex->sphead->add_instr(i); sp->add_instr(
lex->sphead->m_flags|= sp_head::IN_SIMPLE_CASE; new sp_instr_set_case_expr(sp->instructions(),
lex->sphead->restore_lex(YYTHD); parsing_ctx,
case_expr_id,
$3,
lex));
sp->m_flags|= sp_head::IN_SIMPLE_CASE;
sp->restore_lex(YYTHD);
} }
sp_case END CASE_SYM sp_case END CASE_SYM
{ {
Lex->spcont->pop_pvar(); Lex->spcont->pop_case_expr_id();
} }
| sp_labeled_control | sp_labeled_control
{} {}
@ -2315,20 +2350,20 @@ sp_case:
i= new sp_instr_jump_if_not(ip, ctx, $2, lex); i= new sp_instr_jump_if_not(ip, ctx, $2, lex);
else else
{ /* Simple case: <caseval> = <whenval> */ { /* Simple case: <caseval> = <whenval> */
LEX_STRING ivar;
ivar.str= (char *)"_tmp_"; Item_case_expr *var;
ivar.length= 5; Item *expr;
Item_splocal *var= new Item_splocal(ivar,
ctx->current_pvars()-1); var= new Item_case_expr(ctx->get_current_case_expr_id());
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (var) if (var)
var->owner= sp; var->m_sp= sp;
#endif #endif
Item *expr= new Item_func_eq(var, $2);
expr= new Item_func_eq(var, $2);
i= new sp_instr_jump_if_not(ip, ctx, expr, lex); i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
lex->variables_used= 1;
} }
sp->push_backpatch(i, ctx->push_label((char *)"", 0)); sp->push_backpatch(i, ctx->push_label((char *)"", 0));
sp->add_instr(i); sp->add_instr(i);
@ -4401,11 +4436,6 @@ optimize:
OPTIMIZE opt_no_write_to_binlog table_or_tables OPTIMIZE opt_no_write_to_binlog table_or_tables
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "OPTIMIZE TABLE");
YYABORT;
}
lex->sql_command = SQLCOM_OPTIMIZE; lex->sql_command = SQLCOM_OPTIMIZE;
lex->no_write_to_binlog= $2; lex->no_write_to_binlog= $2;
lex->check_opt.init(); lex->check_opt.init();
@ -5024,11 +5054,9 @@ simple_expr:
{ {
if ($3->is_splocal()) if ($3->is_splocal())
{ {
LEX_STRING *name;
Item_splocal *il= static_cast<Item_splocal *>($3); Item_splocal *il= static_cast<Item_splocal *>($3);
name= il->my_name(NULL); my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str);
my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
YYABORT; YYABORT;
} }
$$= new Item_default_value(Lex->current_context(), $3); $$= new Item_default_value(Lex->current_context(), $3);
@ -5803,10 +5831,8 @@ join_table:
{ {
YYERROR_UNLESS($1 && ($$=$3)); YYERROR_UNLESS($1 && ($$=$3));
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $3))
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
@ -5818,10 +5844,8 @@ join_table:
{ {
YYERROR_UNLESS($1 && ($$=$3)); YYERROR_UNLESS($1 && ($$=$3));
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $3))
if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
@ -5848,10 +5872,8 @@ join_table:
ON ON
{ {
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $5))
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
@ -5881,10 +5903,8 @@ join_table:
ON ON
{ {
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $1, $5))
if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr expr
{ {
@ -5945,10 +5965,9 @@ table_factor:
ON ON
{ {
/* Change the current name resolution context to a local context. */ /* Change the current name resolution context to a local context. */
Name_resolution_context *on_context; if (push_new_name_resolution_context(YYTHD, $3, $7))
if (!(on_context= make_join_on_context(YYTHD,$3,$7)))
YYABORT; YYABORT;
Lex->push_context(on_context);
} }
expr '}' expr '}'
{ {
@ -6505,7 +6524,7 @@ select_var_ident:
var_list.push_back(var= new my_var($1,1,t->offset,t->type)); var_list.push_back(var= new my_var($1,1,t->offset,t->type));
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (var) if (var)
var->owner= lex->sphead; var->sp= lex->sphead;
#endif #endif
} }
} }
@ -7816,11 +7835,12 @@ simple_ident:
{ {
/* We're compiling a stored procedure and found a variable */ /* We're compiling a stored procedure and found a variable */
Item_splocal *splocal; Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev - splocal= new Item_splocal($1, spv->offset, spv->type,
lex->tok_start_prev -
lex->sphead->m_tmp_query); lex->sphead->m_tmp_query);
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (splocal) if (splocal)
splocal->owner= lex->sphead; splocal->m_sp= lex->sphead;
#endif #endif
$$ = (Item*) splocal; $$ = (Item*) splocal;
lex->variables_used= 1; lex->variables_used= 1;

View file

@ -3080,60 +3080,6 @@ GRANT_INFO *Natural_join_column::grant()
} }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
Check the access rights for the current join column.
columns.
SYNOPSIS
Natural_join_column::check_grants()
DESCRIPTION
Check the access rights to a column from a natural join in a generic
way that hides the heterogeneity of the column representation - whether
it is a view or a stored table colum.
RETURN
FALSE The column can be accessed
TRUE There are no access rights to all equivalent columns
*/
bool
Natural_join_column::check_grants(THD *thd, const char *name, uint length)
{
GRANT_INFO *grant;
const char *db_name;
const char *table_name;
Security_context *save_security_ctx= thd->security_ctx;
Security_context *new_sctx= table_ref->security_ctx;
bool res;
if (view_field)
{
DBUG_ASSERT(table_field == NULL);
grant= &(table_ref->grant);
db_name= table_ref->view_db.str;
table_name= table_ref->view_name.str;
}
else
{
DBUG_ASSERT(table_field && view_field == NULL);
grant= &(table_ref->table->grant);
db_name= table_ref->table->s->db.str;
table_name= table_ref->table->s->table_name.str;
}
if (new_sctx)
thd->security_ctx= new_sctx;
res= check_grant_column(thd, grant, db_name, table_name, name, length);
thd->security_ctx= save_security_ctx;
return res;
}
#endif
void Field_iterator_view::set(TABLE_LIST *table) void Field_iterator_view::set(TABLE_LIST *table)
{ {
DBUG_ASSERT(table->field_translation); DBUG_ASSERT(table->field_translation);
@ -3176,8 +3122,9 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
if (view->schema_table_reformed) if (view->schema_table_reformed)
{ {
/* /*
In case of SHOW command (schema_table_reformed set) all items are Translation table items are always Item_fields and already fixed
fixed ('mysql_schema_table' function). So we can return directly the
field. This case happens only for 'show & where' commands.
*/ */
DBUG_ASSERT(field && field->fixed); DBUG_ASSERT(field && field->fixed);
DBUG_RETURN(field); DBUG_RETURN(field);
@ -3209,21 +3156,14 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
void Field_iterator_natural_join::set(TABLE_LIST *table_ref) void Field_iterator_natural_join::set(TABLE_LIST *table_ref)
{ {
DBUG_ASSERT(table_ref->join_columns); DBUG_ASSERT(table_ref->join_columns);
delete column_ref_it; column_ref_it.init(*(table_ref->join_columns));
cur_column_ref= column_ref_it++;
/*
TODO: try not to allocate new iterator every time. If we have to,
then check for out of memory condition.
*/
column_ref_it= new List_iterator_fast<Natural_join_column>
(*(table_ref->join_columns));
cur_column_ref= (*column_ref_it)++;
} }
void Field_iterator_natural_join::next() void Field_iterator_natural_join::next()
{ {
cur_column_ref= (*column_ref_it)++; cur_column_ref= column_ref_it++;
DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field || DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field ||
cur_column_ref->table_ref->table == cur_column_ref->table_ref->table ==
cur_column_ref->table_field->table); cur_column_ref->table_field->table);
@ -3350,7 +3290,6 @@ GRANT_INFO *Field_iterator_table_ref::grant()
SYNOPSIS SYNOPSIS
Field_iterator_table_ref::get_or_create_column_ref() Field_iterator_table_ref::get_or_create_column_ref()
thd [in] pointer to current thread
is_created [out] set to TRUE if the column was created, is_created [out] set to TRUE if the column was created,
FALSE if we return an already created colum FALSE if we return an already created colum
@ -3363,7 +3302,7 @@ GRANT_INFO *Field_iterator_table_ref::grant()
*/ */
Natural_join_column * Natural_join_column *
Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created) Field_iterator_table_ref::get_or_create_column_ref(bool *is_created)
{ {
Natural_join_column *nj_col; Natural_join_column *nj_col;
@ -3397,6 +3336,41 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, bool *is_created)
} }
/*
Return an existing reference to a column of a natural/using join.
SYNOPSIS
Field_iterator_table_ref::get_natural_column_ref()
DESCRIPTION
The method should be called in contexts where it is expected that
all natural join columns are already created, and that the column
being retrieved is a Natural_join_column.
RETURN
# Pointer to a column of a natural join (or its operand)
NULL No memory to allocate the column
*/
Natural_join_column *
Field_iterator_table_ref::get_natural_column_ref()
{
Natural_join_column *nj_col;
DBUG_ASSERT(field_it == &natural_join_it);
/*
The field belongs to a NATURAL join, therefore the column reference was
already created via one of the two constructor calls above. In this case
we just return the already created column reference.
*/
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col &&
(!nj_col->table_field ||
nj_col->table_ref->table == nj_col->table_field->table));
return nj_col;
}
/***************************************************************************** /*****************************************************************************
** Instansiate templates ** Instansiate templates
*****************************************************************************/ *****************************************************************************/

View file

@ -432,9 +432,6 @@ public:
const char *table_name(); const char *table_name();
const char *db_name(); const char *db_name();
GRANT_INFO *grant(); GRANT_INFO *grant();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
bool check_grants(THD *thd, const char *name, uint length);
#endif
}; };
@ -760,11 +757,11 @@ public:
class Field_iterator_natural_join: public Field_iterator class Field_iterator_natural_join: public Field_iterator
{ {
List_iterator_fast<Natural_join_column> *column_ref_it; List_iterator_fast<Natural_join_column> column_ref_it;
Natural_join_column *cur_column_ref; Natural_join_column *cur_column_ref;
public: public:
Field_iterator_natural_join() :column_ref_it(NULL), cur_column_ref(NULL) {} Field_iterator_natural_join() :cur_column_ref(NULL) {}
~Field_iterator_natural_join() { delete column_ref_it; } ~Field_iterator_natural_join() {}
void set(TABLE_LIST *table); void set(TABLE_LIST *table);
void next(); void next();
bool end_of_fields() { return !cur_column_ref; } bool end_of_fields() { return !cur_column_ref; }
@ -811,7 +808,8 @@ public:
GRANT_INFO *grant(); GRANT_INFO *grant();
Item *create_item(THD *thd) { return field_it->create_item(thd); } Item *create_item(THD *thd) { return field_it->create_item(thd); }
Field *field() { return field_it->field(); } Field *field() { return field_it->field(); }
Natural_join_column *get_or_create_column_ref(THD *thd, bool *is_created); Natural_join_column *get_or_create_column_ref(bool *is_created);
Natural_join_column *get_natural_column_ref();
}; };

View file

@ -1,5 +1,5 @@
/*- /*-
* $Id: LICENSE,v 11.12 2004/03/30 20:49:44 bostic Exp $ * $Id: LICENSE,v 12.1 2005/06/16 20:20:10 bostic Exp $
*/ */
The following is the license that applies to this copy of the Berkeley DB The following is the license that applies to this copy of the Berkeley DB
@ -10,7 +10,7 @@ the Web at http://www.sleepycat.com.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/* /*
* Copyright (c) 1990-2004 * Copyright (c) 1990-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without

View file

@ -24,13 +24,12 @@ top_srcdir = @top_srcdir@
bdb_build = build_unix bdb_build = build_unix
files = LICENSE Makefile Makefile.in README files = LICENSE Makefile Makefile.in README
subdirs = btree build_vxworks build_win32 clib common cxx db dbinc \ subdirs = btree build_win32 clib common cxx db dbinc \
dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \ dbinc_auto db185 db_archive db_checkpoint db_deadlock db_dump \
db_dump185 db_load db_printlog db_recover db_stat db_upgrade \ db_dump185 db_hotbackup db_load db_printlog db_recover db_stat db_upgrade \
db_verify dbm dbreg dist env examples_c examples_cxx fileops hash \ db_verify dbm dbreg dist env fileops hash \
hsearch hmac include java libdb_java lock log mp mutex os os_vxworks \ hsearch hmac include lock log mp mutex os \
os_win32 perl.BerkeleyDB perl.DB_File qam rep rpc_client rpc_server tcl \ os_win32 qam rep txn xa sequence
test txn xa sequence
@SET_MAKE@ @SET_MAKE@

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_compare.c,v 11.20 2004/02/21 15:54:44 bostic Exp $ * $Id: bt_compare.c,v 12.1 2005/06/16 20:20:13 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_conv.c,v 11.15 2004/01/28 03:35:48 bostic Exp $ * $Id: bt_conv.c,v 12.2 2005/06/16 20:20:13 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -88,7 +88,7 @@ __bam_mswap(pg)
p = (u_int8_t *)pg + sizeof(DBMETA); p = (u_int8_t *)pg + sizeof(DBMETA);
SWAP32(p); /* maxkey */ p += sizeof(u_int32_t); /* unused */
SWAP32(p); /* minkey */ SWAP32(p); /* minkey */
SWAP32(p); /* re_len */ SWAP32(p); /* re_len */
SWAP32(p); /* re_pad */ SWAP32(p); /* re_pad */

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_curadj.c,v 11.37 2004/03/13 14:11:33 bostic Exp $ * $Id: bt_curadj.c,v 12.3 2005/07/20 16:50:45 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -35,14 +35,14 @@ static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t));
* Update the cursors when items are deleted and when already deleted * Update the cursors when items are deleted and when already deleted
* items are overwritten. Return the number of relevant cursors found. * items are overwritten. Return the number of relevant cursors found.
* *
* PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int)); * PUBLIC: int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int, int *));
*/ */
int int
__bam_ca_delete(dbp, pgno, indx, delete) __bam_ca_delete(dbp, pgno, indx, delete, countp)
DB *dbp; DB *dbp;
db_pgno_t pgno; db_pgno_t pgno;
u_int32_t indx; u_int32_t indx;
int delete; int delete, *countp;
{ {
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
DB *ldbp; DB *ldbp;
@ -63,11 +63,11 @@ __bam_ca_delete(dbp, pgno, indx, delete)
* Each cursor is single-threaded, so we only need to lock the * Each cursor is single-threaded, so we only need to lock the
* list of DBs and then the list of cursors in each DB. * list of DBs and then the list of cursors in each DB.
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (count = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (count = 0, ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
@ -92,23 +92,26 @@ __bam_ca_delete(dbp, pgno, indx, delete)
++count; ++count;
} }
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (count); if (countp != NULL)
*countp = count;
return (0);
} }
/* /*
* __ram_ca_delete -- * __ram_ca_delete --
* Return the number of relevant cursors. * Return if any relevant cursors found.
* *
* PUBLIC: int __ram_ca_delete __P((DB *, db_pgno_t)); * PUBLIC: int __ram_ca_delete __P((DB *, db_pgno_t, int *));
*/ */
int int
__ram_ca_delete(dbp, root_pgno) __ram_ca_delete(dbp, root_pgno, foundp)
DB *dbp; DB *dbp;
db_pgno_t root_pgno; db_pgno_t root_pgno;
int *foundp;
{ {
DB *ldbp; DB *ldbp;
DBC *dbc; DBC *dbc;
@ -121,19 +124,21 @@ __ram_ca_delete(dbp, root_pgno)
/* /*
* Review the cursors. See the comment in __bam_ca_delete(). * Review the cursors. See the comment in __bam_ca_delete().
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; found == 0 && ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
found == 0 && dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) found == 0 && dbc != NULL; dbc = TAILQ_NEXT(dbc, links))
if (dbc->internal->root == root_pgno) if (dbc->internal->root == root_pgno)
found = 1; found = 1;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (found);
*foundp = found;
return (0);
} }
/* /*
@ -166,11 +171,11 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -188,9 +193,9 @@ __bam_ca_di(my_dbc, pgno, indx, adjust)
found = 1; found = 1;
} }
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) { if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0, if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0,
@ -289,11 +294,11 @@ __bam_ca_dup(my_dbc, first, fpgno, fi, tpgno, ti)
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); loop: MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
/* Find cursors pointing to this record. */ /* Find cursors pointing to this record. */
@ -308,7 +313,7 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
if (orig_cp->opd != NULL) if (orig_cp->opd != NULL)
continue; continue;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
/* [#8032] /* [#8032]
DB_ASSERT(!STD_LOCKING(dbc) || DB_ASSERT(!STD_LOCKING(dbc) ||
orig_cp->lock_mode != DB_LOCK_NG); orig_cp->lock_mode != DB_LOCK_NG);
@ -321,9 +326,9 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
/* We released the mutex to get a cursor, start over. */ /* We released the mutex to get a cursor, start over. */
goto loop; goto loop;
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) { if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
@ -359,11 +364,11 @@ __bam_ca_undodup(dbp, first, fpgno, fi, ti)
/* /*
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); loop: MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
orig_cp = (BTREE_CURSOR *)dbc->internal; orig_cp = (BTREE_CURSOR *)dbc->internal;
@ -377,11 +382,10 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
*/ */
if (orig_cp->pgno != fpgno || if (orig_cp->pgno != fpgno ||
orig_cp->indx != first || orig_cp->indx != first ||
orig_cp->opd == NULL || orig_cp->opd == NULL || ((BTREE_CURSOR *)
((BTREE_CURSOR *)orig_cp->opd->internal)->indx orig_cp->opd->internal)->indx != ti)
!= ti)
continue; continue;
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
if ((ret = __db_c_close(orig_cp->opd)) != 0) if ((ret = __db_c_close(orig_cp->opd)) != 0)
return (ret); return (ret);
orig_cp->opd = NULL; orig_cp->opd = NULL;
@ -392,9 +396,9 @@ loop: MUTEX_THREAD_LOCK(dbenv, dbp->mutexp);
*/ */
goto loop; goto loop;
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0); return (0);
} }
@ -425,11 +429,11 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -444,9 +448,9 @@ __bam_ca_rsplit(my_dbc, fpgno, tpgno)
found = 1; found = 1;
} }
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) { if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, my_dbc->txn, if ((ret = __bam_curadj_log(dbp, my_dbc->txn,
@ -493,11 +497,11 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
* records split to the left page. * records split to the left page.
*/ */
found = 0; found = 0;
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -519,9 +523,9 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
} }
} }
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
if (found != 0 && DBC_LOGGING(my_dbc)) { if (found != 0 && DBC_LOGGING(my_dbc)) {
if ((ret = __bam_curadj_log(dbp, if ((ret = __bam_curadj_log(dbp,
@ -540,10 +544,10 @@ __bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft)
* left and the right pages. * left and the right pages.
* Called only during undo processing. * Called only during undo processing.
* *
* PUBLIC: void __bam_ca_undosplit __P((DB *, * PUBLIC: int __bam_ca_undosplit __P((DB *,
* PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t)); * PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t));
*/ */
void int
__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx) __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
DB *dbp; DB *dbp;
db_pgno_t frompgno, topgno, lpgno; db_pgno_t frompgno, topgno, lpgno;
@ -562,11 +566,11 @@ __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
* When backing out a split, we move the cursor back * When backing out a split, we move the cursor back
* to the original offset and bump it by the split_indx. * to the original offset and bump it by the split_indx.
*/ */
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -578,7 +582,9 @@ __bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx)
} else if (cp->pgno == lpgno) } else if (cp->pgno == lpgno)
cp->pgno = frompgno; cp->pgno = frompgno;
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (0);
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_cursor.c,v 11.190 2004/09/22 21:46:32 ubell Exp $ * $Id: bt_cursor.c,v 12.7 2005/08/08 14:27:59 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -26,10 +26,8 @@ static int __bam_bulk __P((DBC *, DBT *, u_int32_t));
static int __bam_c_close __P((DBC *, db_pgno_t, int *)); static int __bam_c_close __P((DBC *, db_pgno_t, int *));
static int __bam_c_del __P((DBC *)); static int __bam_c_del __P((DBC *));
static int __bam_c_destroy __P((DBC *)); static int __bam_c_destroy __P((DBC *));
static int __bam_c_first __P((DBC *));
static int __bam_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); static int __bam_c_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *));
static int __bam_c_getstack __P((DBC *)); static int __bam_c_getstack __P((DBC *));
static int __bam_c_last __P((DBC *));
static int __bam_c_next __P((DBC *, int, int)); static int __bam_c_next __P((DBC *, int, int));
static int __bam_c_physdel __P((DBC *)); static int __bam_c_physdel __P((DBC *));
static int __bam_c_prev __P((DBC *)); static int __bam_c_prev __P((DBC *));
@ -68,21 +66,6 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep)); \ ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep)); \
} while (0) } while (0)
#undef ACQUIRE_COUPLE
#define ACQUIRE_COUPLE(dbc, mode, lpgno, lock, fpgno, pagep, ret) do { \
DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \
if ((pagep) != NULL) { \
ret = __memp_fput(__mpf, pagep, 0); \
pagep = NULL; \
} else \
ret = 0; \
if ((ret) == 0 && STD_LOCKING(dbc)) \
ret = __db_lget(dbc, \
LCK_COUPLE_ALWAYS, lpgno, mode, 0, &(lock)); \
if ((ret) == 0) \
ret = __memp_fget(__mpf, &(fpgno), 0, &(pagep)); \
} while (0)
/* Acquire a new page/lock for a cursor. */ /* Acquire a new page/lock for a cursor. */
#undef ACQUIRE_CUR #undef ACQUIRE_CUR
#define ACQUIRE_CUR(dbc, mode, p, ret) do { \ #define ACQUIRE_CUR(dbc, mode, p, ret) do { \
@ -96,23 +79,6 @@ static int __bam_isopd __P((DBC *, db_pgno_t *));
} \ } \
} while (0) } while (0)
/*
* Acquire a new page/lock for a cursor and release the previous.
* This is typically used when descending a tree and we do not
* want to hold the interior nodes locked.
*/
#undef ACQUIRE_CUR_COUPLE
#define ACQUIRE_CUR_COUPLE(dbc, mode, p, ret) do { \
BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \
if (p != __cp->pgno) \
__cp->pgno = PGNO_INVALID; \
ACQUIRE_COUPLE(dbc, mode, p, __cp->lock, p, __cp->page, ret); \
if ((ret) == 0) { \
__cp->pgno = p; \
__cp->lock_mode = (mode); \
} \
} while (0)
/* /*
* Acquire a write lock if we don't already have one. * Acquire a write lock if we don't already have one.
* *
@ -196,11 +162,11 @@ __bam_c_init(dbc, dbtype)
/* Allocate/initialize the internal structure. */ /* Allocate/initialize the internal structure. */
if (dbc->internal == NULL && (ret = if (dbc->internal == NULL && (ret =
__os_malloc(dbenv, sizeof(BTREE_CURSOR), &dbc->internal)) != 0) __os_calloc(dbenv, 1, sizeof(BTREE_CURSOR), &dbc->internal)) != 0)
return (ret); return (ret);
/* Initialize methods. */ /* Initialize methods. */
dbc->c_close = __db_c_close; dbc->c_close = __db_c_close_pp;
dbc->c_count = __db_c_count_pp; dbc->c_count = __db_c_count_pp;
dbc->c_del = __db_c_del_pp; dbc->c_del = __db_c_del_pp;
dbc->c_dup = __db_c_dup_pp; dbc->c_dup = __db_c_dup_pp;
@ -257,8 +223,11 @@ __bam_c_refresh(dbc)
LOCK_INIT(cp->lock); LOCK_INIT(cp->lock);
cp->lock_mode = DB_LOCK_NG; cp->lock_mode = DB_LOCK_NG;
cp->sp = cp->csp = cp->stack; if (cp->sp == NULL) {
cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]); cp->sp = cp->stack;
cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]);
}
BT_STK_CLR(cp);
/* /*
* The btree leaf page data structures require that two key/data pairs * The btree leaf page data structures require that two key/data pairs
@ -308,7 +277,7 @@ __bam_c_close(dbc, root_pgno, rmroot)
DBC *dbc_opd, *dbc_c; DBC *dbc_opd, *dbc_c;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *h; PAGE *h;
int cdb_lock, ret; int cdb_lock, count, ret;
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; mpf = dbp->mpf;
@ -378,22 +347,28 @@ __bam_c_close(dbc, root_pgno, rmroot)
dbc_c = dbc; dbc_c = dbc;
switch (dbc->dbtype) { switch (dbc->dbtype) {
case DB_BTREE: /* Case #1, #3. */ case DB_BTREE: /* Case #1, #3. */
if (__bam_ca_delete(dbp, cp->pgno, cp->indx, 1) == 0) if ((ret = __bam_ca_delete(
dbp, cp->pgno, cp->indx, 1, &count)) != 0)
goto err;
if (count == 0)
goto lock; goto lock;
goto done; goto done;
case DB_RECNO: case DB_RECNO:
if (!F_ISSET(dbc, DBC_OPD)) /* Case #1. */ if (!F_ISSET(dbc, DBC_OPD)) /* Case #1. */
goto done; goto done;
/* Case #3. */ /* Case #3. */
if (__ram_ca_delete(dbp, cp->root) == 0) if ((ret = __ram_ca_delete(dbp, cp->root, &count)) != 0)
goto err;
if (count == 0)
goto lock; goto lock;
goto done; goto done;
case DB_HASH: case DB_HASH:
case DB_QUEUE: case DB_QUEUE:
case DB_UNKNOWN: case DB_UNKNOWN:
default: default:
return (__db_unknown_type(dbp->dbenv, ret = __db_unknown_type(dbp->dbenv,
"__bam_c_close", dbc->dbtype)); "__bam_c_close", dbc->dbtype);
goto err;
} }
} }
@ -414,20 +389,26 @@ __bam_c_close(dbc, root_pgno, rmroot)
dbc_c = dbc_opd; dbc_c = dbc_opd;
switch (dbc_opd->dbtype) { switch (dbc_opd->dbtype) {
case DB_BTREE: case DB_BTREE:
if (__bam_ca_delete( if ((ret = __bam_ca_delete(
dbp, cp_opd->pgno, cp_opd->indx, 1) == 0) dbp, cp_opd->pgno, cp_opd->indx, 1, &count)) != 0)
goto err;
if (count == 0)
goto lock; goto lock;
goto done; goto done;
case DB_RECNO: case DB_RECNO:
if (__ram_ca_delete(dbp, cp_opd->root) == 0) if ((ret =
__ram_ca_delete(dbp, cp_opd->root, &count)) != 0)
goto err;
if (count == 0)
goto lock; goto lock;
goto done; goto done;
case DB_HASH: case DB_HASH:
case DB_QUEUE: case DB_QUEUE:
case DB_UNKNOWN: case DB_UNKNOWN:
default: default:
return (__db_unknown_type( ret = __db_unknown_type(
dbp->dbenv, "__bam_c_close", dbc->dbtype)); dbp->dbenv, "__bam_c_close", dbc->dbtype);
goto err;
} }
} }
goto done; goto done;
@ -588,8 +569,14 @@ static int
__bam_c_destroy(dbc) __bam_c_destroy(dbc)
DBC *dbc; DBC *dbc;
{ {
BTREE_CURSOR *cp;
cp = (BTREE_CURSOR *)dbc->internal;
/* Discard the structures. */ /* Discard the structures. */
__os_free(dbc->dbp->dbenv, dbc->internal); if (cp->sp != cp->stack)
__os_free(dbc->dbp->dbenv, cp->sp);
__os_free(dbc->dbp->dbenv, cp);
return (0); return (0);
} }
@ -693,7 +680,7 @@ __bam_c_del(dbc)
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
DB *dbp; DB *dbp;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
int ret, t_ret; int count, ret, t_ret;
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; mpf = dbp->mpf;
@ -760,9 +747,12 @@ err: /*
cp->page = NULL; cp->page = NULL;
/* Update the cursors last, after all chance of failure is past. */ /*
* Update the cursors last, after all chance of recoverable failure
* is past.
*/
if (ret == 0) if (ret == 0)
(void)__bam_ca_delete(dbp, cp->pgno, cp->indx, 1); ret = __bam_ca_delete(dbp, cp->pgno, cp->indx, 1, &count);
return (ret); return (ret);
} }
@ -846,7 +836,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
break; break;
case DB_FIRST: case DB_FIRST:
newopd = 1; newopd = 1;
if ((ret = __bam_c_first(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, flags, &exact)) != 0)
goto err; goto err;
break; break;
case DB_GET_BOTH: case DB_GET_BOTH:
@ -910,13 +901,15 @@ __bam_c_get(dbc, key, data, flags, pgnop)
break; break;
case DB_LAST: case DB_LAST:
newopd = 1; newopd = 1;
if ((ret = __bam_c_last(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, flags, &exact)) != 0)
goto err; goto err;
break; break;
case DB_NEXT: case DB_NEXT:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_first(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_FIRST, &exact)) != 0)
goto err; goto err;
} else } else
if ((ret = __bam_c_next(dbc, 1, 0)) != 0) if ((ret = __bam_c_next(dbc, 1, 0)) != 0)
@ -933,7 +926,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_NEXT_NODUP: case DB_NEXT_NODUP:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_first(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_FIRST, &exact)) != 0)
goto err; goto err;
} else } else
do { do {
@ -944,7 +938,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_PREV: case DB_PREV:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_last(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_LAST, &exact)) != 0)
goto err; goto err;
} else } else
if ((ret = __bam_c_prev(dbc)) != 0) if ((ret = __bam_c_prev(dbc)) != 0)
@ -953,7 +948,8 @@ __bam_c_get(dbc, key, data, flags, pgnop)
case DB_PREV_NODUP: case DB_PREV_NODUP:
newopd = 1; newopd = 1;
if (cp->pgno == PGNO_INVALID) { if (cp->pgno == PGNO_INVALID) {
if ((ret = __bam_c_last(dbc)) != 0) if ((ret = __bam_c_search(dbc,
PGNO_INVALID, NULL, DB_LAST, &exact)) != 0)
goto err; goto err;
} else } else
do { do {
@ -2136,99 +2132,6 @@ __bam_c_writelock(dbc)
return (ret); return (ret);
} }
/*
* __bam_c_first --
* Return the first record.
*/
static int
__bam_c_first(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
db_pgno_t pgno;
int ret;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/* Walk down the left-hand side of the tree. */
for (pgno = cp->root;;) {
ACQUIRE_CUR_COUPLE(dbc, DB_LOCK_READ, pgno, ret);
if (ret != 0)
return (ret);
/* If we find a leaf page, we're done. */
if (ISLEAF(cp->page))
break;
pgno = GET_BINTERNAL(dbc->dbp, cp->page, 0)->pgno;
}
/* If we want a write lock instead of a read lock, get it now. */
if (F_ISSET(dbc, DBC_RMW)) {
ACQUIRE_WRITE_LOCK(dbc, ret);
if (ret != 0)
return (ret);
}
cp->indx = 0;
/* If on an empty page or a deleted record, move to the next one. */
if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))
if ((ret = __bam_c_next(dbc, 0, 0)) != 0)
return (ret);
return (0);
}
/*
* __bam_c_last --
* Return the last record.
*/
static int
__bam_c_last(dbc)
DBC *dbc;
{
BTREE_CURSOR *cp;
db_pgno_t pgno;
int ret;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/* Walk down the right-hand side of the tree. */
for (pgno = cp->root;;) {
ACQUIRE_CUR_COUPLE(dbc, DB_LOCK_READ, pgno, ret);
if (ret != 0)
return (ret);
/* If we find a leaf page, we're done. */
if (ISLEAF(cp->page))
break;
pgno = GET_BINTERNAL(dbc->dbp, cp->page,
NUM_ENT(cp->page) - O_INDX)->pgno;
}
/* If we want a write lock instead of a read lock, get it now. */
if (F_ISSET(dbc, DBC_RMW)) {
ACQUIRE_WRITE_LOCK(dbc, ret);
if (ret != 0)
return (ret);
}
cp->indx = NUM_ENT(cp->page) == 0 ? 0 :
NUM_ENT(cp->page) -
(TYPE(cp->page) == P_LBTREE ? P_INDX : O_INDX);
/* If on an empty page or a deleted record, move to the previous one. */
if (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))
if ((ret = __bam_c_prev(dbc)) != 0)
return (ret);
return (0);
}
/* /*
* __bam_c_next -- * __bam_c_next --
* Move to the next record. * Move to the next record.
@ -2398,6 +2301,12 @@ __bam_c_search(dbc, root_pgno, key, flags, exactp)
return (ret); return (ret);
switch (flags) { switch (flags) {
case DB_FIRST:
sflags = (F_ISSET(dbc, DBC_RMW) ? S_WRITE : S_READ) | S_MIN;
goto search;
case DB_LAST:
sflags = (F_ISSET(dbc, DBC_RMW) ? S_WRITE : S_READ) | S_MAX;
goto search;
case DB_SET_RECNO: case DB_SET_RECNO:
if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0) if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0)
return (ret); return (ret);
@ -2575,7 +2484,6 @@ search: if ((ret = __bam_search(dbc, root_pgno,
default: default:
return (__db_unknown_flag(dbp->dbenv, "__bam_c_search", flags)); return (__db_unknown_flag(dbp->dbenv, "__bam_c_search", flags));
} }
/* Initialize the cursor from the stack. */ /* Initialize the cursor from the stack. */
cp->page = cp->csp->page; cp->page = cp->csp->page;
cp->pgno = cp->csp->page->pgno; cp->pgno = cp->csp->page->pgno;
@ -2583,6 +2491,16 @@ search: if ((ret = __bam_search(dbc, root_pgno,
cp->lock = cp->csp->lock; cp->lock = cp->csp->lock;
cp->lock_mode = cp->csp->lock_mode; cp->lock_mode = cp->csp->lock_mode;
/* If on an empty page or a deleted record, move to the next one. */
if (flags == DB_FIRST &&
(NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc)))
if ((ret = __bam_c_next(dbc, 0, 0)) != 0)
return (ret);
if (flags == DB_LAST &&
(NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc)))
if ((ret = __bam_c_prev(dbc)) != 0)
return (ret);
return (0); return (0);
} }
@ -2597,15 +2515,10 @@ __bam_c_physdel(dbc)
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
DB *dbp; DB *dbp;
DBT key; DBT key;
DB_LOCK lock; int delete_page, empty_page, exact, ret;
DB_MPOOLFILE *mpf;
PAGE *h;
db_pgno_t pgno;
int delete_page, empty_page, exact, level, ret;
dbp = dbc->dbp; dbp = dbc->dbp;
memset(&key, 0, sizeof(DBT)); memset(&key, 0, sizeof(DBT));
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
delete_page = empty_page = ret = 0; delete_page = empty_page = ret = 0;
@ -2683,91 +2596,7 @@ __bam_c_physdel(dbc)
if (!delete_page) if (!delete_page)
return (0); return (0);
/* ret = __bam_search(dbc, PGNO_INVALID, &key, S_DEL, 0, NULL, &exact);
* Call __bam_search to reacquire the empty leaf page, but this time
* get both the leaf page and it's parent, locked. Jump back up the
* tree, until we have the top pair of pages that we want to delete.
* Once we have the top page that we want to delete locked, lock the
* underlying pages and check to make sure they're still empty. If
* they are, delete them.
*/
for (level = LEAFLEVEL;; ++level) {
/* Acquire a page and its parent, locked. */
if ((ret = __bam_search(dbc, PGNO_INVALID,
&key, S_WRPAIR, level, NULL, &exact)) != 0)
return (ret);
/*
* If we reach the root or the parent page isn't going to be
* empty when we delete one record, stop.
*/
h = cp->csp[-1].page;
if (h->pgno == cp->root || NUM_ENT(h) != 1)
break;
/* Discard the stack, retaining no locks. */
(void)__bam_stkrel(dbc, STK_NOLOCK);
}
/*
* Move the stack pointer one after the last entry, we may be about
* to push more items onto the page stack.
*/
++cp->csp;
/*
* cp->csp[-2].page is now the parent page, which we may or may not be
* going to delete, and cp->csp[-1].page is the first page we know we
* are going to delete. Walk down the chain of pages, acquiring pages
* until we've acquired a leaf page. Generally, this shouldn't happen;
* we should only see a single internal page with one item and a single
* leaf page with no items. The scenario where we could see something
* else is if reverse splits were turned off for awhile and then turned
* back on. That could result in all sorts of strangeness, e.g., empty
* pages in the tree, trees that looked like linked lists, and so on.
*
* !!!
* Sheer paranoia: if we find any pages that aren't going to be emptied
* by the delete, someone else added an item while we were walking the
* tree, and we discontinue the delete. Shouldn't be possible, but we
* check regardless.
*/
for (h = cp->csp[-1].page;;) {
if (ISLEAF(h)) {
if (NUM_ENT(h) != 0)
break;
break;
} else
if (NUM_ENT(h) != 1)
break;
/*
* Get the next page, write lock it and push it onto the stack.
* We know it's index 0, because it can only have one element.
*/
switch (TYPE(h)) {
case P_IBTREE:
pgno = GET_BINTERNAL(dbp, h, 0)->pgno;
break;
case P_IRECNO:
pgno = GET_RINTERNAL(dbp, h, 0)->pgno;
break;
default:
return (__db_pgfmt(dbp->dbenv, PGNO(h)));
}
if ((ret =
__db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &lock)) != 0)
break;
if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
break;
BT_STK_PUSH(dbp->dbenv, cp, h, 0, lock, DB_LOCK_WRITE, ret);
if (ret != 0)
break;
}
/* Adjust the cursor stack to reference the last page on the stack. */
BT_STK_POP(cp);
/* /*
* If everything worked, delete the stack, otherwise, release the * If everything worked, delete the stack, otherwise, release the
@ -2776,7 +2605,7 @@ __bam_c_physdel(dbc)
if (ret == 0) if (ret == 0)
DISCARD_CUR(dbc, ret); DISCARD_CUR(dbc, ret);
if (ret == 0) if (ret == 0)
ret = __bam_dpages(dbc, cp->sp); ret = __bam_dpages(dbc, 1, 0);
else else
(void)__bam_stkrel(dbc, 0); (void)__bam_stkrel(dbc, 0);

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_delete.c,v 11.49 2004/02/27 12:38:28 bostic Exp $ * $Id: bt_delete.c,v 12.13 2005/10/20 18:14:59 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -220,12 +220,13 @@ __bam_adjindx(dbc, h, indx, indx_copy, is_insert)
* __bam_dpages -- * __bam_dpages --
* Delete a set of locked pages. * Delete a set of locked pages.
* *
* PUBLIC: int __bam_dpages __P((DBC *, EPG *)); * PUBLIC: int __bam_dpages __P((DBC *, int, int));
*/ */
int int
__bam_dpages(dbc, stack_epg) __bam_dpages(dbc, use_top, update)
DBC *dbc; DBC *dbc;
EPG *stack_epg; int use_top;
int update;
{ {
BTREE_CURSOR *cp; BTREE_CURSOR *cp;
BINTERNAL *bi; BINTERNAL *bi;
@ -233,7 +234,7 @@ __bam_dpages(dbc, stack_epg)
DBT a, b; DBT a, b;
DB_LOCK c_lock, p_lock; DB_LOCK c_lock, p_lock;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
EPG *epg; EPG *epg, *save_sp, *stack_epg;
PAGE *child, *parent; PAGE *child, *parent;
db_indx_t nitems; db_indx_t nitems;
db_pgno_t pgno, root_pgno; db_pgno_t pgno, root_pgno;
@ -243,30 +244,27 @@ __bam_dpages(dbc, stack_epg)
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf; mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
nitems = 0;
pgno = PGNO_INVALID;
/* /*
* We have the entire stack of deletable pages locked. * We have the entire stack of deletable pages locked.
* *
* Btree calls us with a pointer to the beginning of a stack, where * Btree calls us with the first page in the stack is to have a
* the first page in the stack is to have a single item deleted, and * single item deleted, and the rest of the pages are to be removed.
* the rest of the pages are to be removed.
* *
* Recno calls us with a pointer into the middle of the stack, where * Recno always has a stack to the root and __bam_merge operations
* the referenced page is to have a single item deleted, and pages * may have unneeded items in the sack. We find the lowest page
* after the stack reference are to be removed. * in the stack that has more than one record in it and start there.
*
* First, discard any pages that we don't care about.
*/ */
ret = 0; ret = 0;
for (epg = cp->sp; epg < stack_epg; ++epg) { if (use_top)
if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0) stack_epg = cp->sp;
ret = t_ret; else
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) for (stack_epg = cp->csp; stack_epg > cp->sp; --stack_epg)
ret = t_ret; if (NUM_ENT(stack_epg->page) > 1)
} break;
if (ret != 0) epg = stack_epg;
goto err;
/* /*
* !!! * !!!
* There is an interesting deadlock situation here. We have to relink * There is an interesting deadlock situation here. We have to relink
@ -276,8 +274,9 @@ __bam_dpages(dbc, stack_epg)
* It will deadlock here. Before we unlink the subtree, we relink the * It will deadlock here. Before we unlink the subtree, we relink the
* leaf page chain. * leaf page chain.
*/ */
if ((ret = __bam_relink(dbc, cp->csp->page, NULL)) != 0) if (LEVEL(cp->csp->page) == 1 &&
goto err; (ret = __bam_relink(dbc, cp->csp->page, PGNO_INVALID)) != 0)
goto discard;
/* /*
* Delete the last item that references the underlying pages that are * Delete the last item that references the underlying pages that are
@ -288,9 +287,18 @@ __bam_dpages(dbc, stack_epg)
* immediately. * immediately.
*/ */
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0) if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto err; goto discard;
if ((ret = __bam_ca_di(dbc, PGNO(epg->page), epg->indx, -1)) != 0) if ((ret = __bam_ca_di(dbc, PGNO(epg->page), epg->indx, -1)) != 0)
goto err; goto discard;
if (update && epg->indx == 0) {
save_sp = cp->csp;
cp->csp = epg;
ret = __bam_pupdate(dbc, epg->page);
cp->csp = save_sp;
if (ret != 0)
goto discard;
}
pgno = PGNO(epg->page); pgno = PGNO(epg->page);
nitems = NUM_ENT(epg->page); nitems = NUM_ENT(epg->page);
@ -301,6 +309,17 @@ __bam_dpages(dbc, stack_epg)
if (ret != 0) if (ret != 0)
goto err_inc; goto err_inc;
/* Then, discard any pages that we don't care about. */
discard: for (epg = cp->sp; epg < stack_epg; ++epg) {
if ((t_ret = __memp_fput(mpf, epg->page, 0)) != 0 && ret == 0)
ret = t_ret;
epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret;
}
if (ret != 0)
goto err;
/* Free the rest of the pages in the stack. */ /* Free the rest of the pages in the stack. */
while (++epg <= cp->csp) { while (++epg <= cp->csp) {
/* /*
@ -310,13 +329,24 @@ __bam_dpages(dbc, stack_epg)
* be referenced by a cursor. * be referenced by a cursor.
*/ */
if (NUM_ENT(epg->page) != 0) { if (NUM_ENT(epg->page) != 0) {
DB_ASSERT(NUM_ENT(epg->page) == 1); DB_ASSERT(LEVEL(epg->page) != 1);
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0) if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
goto err; goto err;
/*
* Sheer paranoia: if we find any pages that aren't
* emptied by the delete, someone else added an item
* while we were walking the tree, and we discontinue
* the delete. Shouldn't be possible, but we check
* regardless.
*/
if (NUM_ENT(epg->page) != 0)
goto err;
} }
ret = __db_free(dbc, epg->page); ret = __db_free(dbc, epg->page);
if (cp->page == epg->page)
cp->page = NULL;
epg->page = NULL; epg->page = NULL;
if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -468,12 +498,13 @@ stop: done = 1;
* __bam_relink -- * __bam_relink --
* Relink around a deleted page. * Relink around a deleted page.
* *
* PUBLIC: int __bam_relink __P((DBC *, PAGE *, PAGE **)); * PUBLIC: int __bam_relink __P((DBC *, PAGE *, db_pgno_t));
*/ */
int int
__bam_relink(dbc, pagep, new_next) __bam_relink(dbc, pagep, new_pgno)
DBC *dbc; DBC *dbc;
PAGE *pagep, **new_next; PAGE *pagep;
db_pgno_t new_pgno;
{ {
DB *dbp; DB *dbp;
PAGE *np, *pp; PAGE *np, *pp;
@ -519,7 +550,7 @@ __bam_relink(dbc, pagep, new_next)
/* Log the change. */ /* Log the change. */
if (DBC_LOGGING(dbc)) { if (DBC_LOGGING(dbc)) {
if ((ret = __bam_relink_log(dbp, dbc->txn, &ret_lsn, 0, if ((ret = __bam_relink_log(dbp, dbc->txn, &ret_lsn, 0,
pagep->pgno, &pagep->lsn, pagep->prev_pgno, plsnp, pagep->pgno, new_pgno, pagep->prev_pgno, plsnp,
pagep->next_pgno, nlsnp)) != 0) pagep->next_pgno, nlsnp)) != 0)
goto err; goto err;
} else } else
@ -528,33 +559,27 @@ __bam_relink(dbc, pagep, new_next)
np->lsn = ret_lsn; np->lsn = ret_lsn;
if (pp != NULL) if (pp != NULL)
pp->lsn = ret_lsn; pp->lsn = ret_lsn;
pagep->lsn = ret_lsn;
/* /*
* Modify and release the two pages. * Modify and release the two pages.
*
* !!!
* The parameter new_next gets set to the page following the page we
* are removing. If there is no following page, then new_next gets
* set to NULL.
*/ */
if (np != NULL) { if (np != NULL) {
np->prev_pgno = pagep->prev_pgno; if (new_pgno == PGNO_INVALID)
if (new_next == NULL) np->prev_pgno = pagep->prev_pgno;
ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY); else
else { np->prev_pgno = new_pgno;
*new_next = np; ret = __memp_fput(mpf, np, DB_MPOOL_DIRTY);
ret = __memp_fset(mpf, np, DB_MPOOL_DIRTY);
}
if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
if (ret != 0) if (ret != 0)
goto err; goto err;
} else if (new_next != NULL) }
*new_next = NULL;
if (pp != NULL) { if (pp != NULL) {
pp->next_pgno = pagep->next_pgno; if (new_pgno == PGNO_INVALID)
pp->next_pgno = pagep->next_pgno;
else
pp->next_pgno = new_pgno;
ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY); ret = __memp_fput(mpf, pp, DB_MPOOL_DIRTY);
if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0) if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -571,3 +596,48 @@ err: if (np != NULL)
(void)__TLPUT(dbc, ppl); (void)__TLPUT(dbc, ppl);
return (ret); return (ret);
} }
/*
* __bam_pupdate --
* Update parent key pointers up the tree.
*
* PUBLIC: int __bam_pupdate __P((DBC *, PAGE *));
*/
int
__bam_pupdate(dbc, lpg)
DBC *dbc;
PAGE *lpg;
{
BTREE_CURSOR *cp;
DB_ENV *dbenv;
EPG *epg;
int ret;
dbenv = dbc->dbp->dbenv;
cp = (BTREE_CURSOR *)dbc->internal;
ret = 0;
/*
* Update the parents up the tree. __bam_pinsert only looks at the
* left child if is a leaf page, so we don't need to change it. We
* just do a delete and insert; a replace is possible but reusing
* pinsert is better.
*/
for (epg = &cp->csp[-1]; epg >= cp->sp; epg--) {
if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0)
return (ret);
epg->indx--;
if ((ret = __bam_pinsert(dbc, epg,
lpg, epg[1].page, BPI_NORECNUM)) != 0) {
if (ret == DB_NEEDSPLIT) {
/* This should not happen. */
__db_err(dbenv,
"Not enough room in parent: %s: page %lu",
dbc->dbp->fname, (u_long)PGNO(epg->page));
ret = __db_panic(dbenv, EINVAL);
}
return (ret);
}
}
return (ret);
}

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_method.c,v 11.38 2004/09/22 03:31:26 bostic Exp $ * $Id: bt_method.c,v 12.2 2005/06/16 20:20:16 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -18,7 +18,6 @@
#include "dbinc/btree.h" #include "dbinc/btree.h"
#include "dbinc/qam.h" #include "dbinc/qam.h"
static int __bam_set_bt_maxkey __P((DB *, u_int32_t));
static int __bam_set_bt_minkey __P((DB *, u_int32_t)); static int __bam_set_bt_minkey __P((DB *, u_int32_t));
static int __bam_set_bt_prefix static int __bam_set_bt_prefix
__P((DB *, size_t(*)(DB *, const DBT *, const DBT *))); __P((DB *, size_t(*)(DB *, const DBT *, const DBT *)));
@ -52,7 +51,6 @@ __bam_db_create(dbp)
t->bt_prefix = __bam_defpfx; t->bt_prefix = __bam_defpfx;
dbp->set_bt_compare = __bam_set_bt_compare; dbp->set_bt_compare = __bam_set_bt_compare;
dbp->set_bt_maxkey = __bam_set_bt_maxkey;
dbp->get_bt_minkey = __bam_get_bt_minkey; dbp->get_bt_minkey = __bam_get_bt_minkey;
dbp->set_bt_minkey = __bam_set_bt_minkey; dbp->set_bt_minkey = __bam_set_bt_minkey;
dbp->set_bt_prefix = __bam_set_bt_prefix; dbp->set_bt_prefix = __bam_set_bt_prefix;
@ -208,31 +206,6 @@ __bam_set_bt_compare(dbp, func)
return (0); return (0);
} }
/*
* __bam_set_bt_maxkey --
* Set the maximum keys per page.
*/
static int
__bam_set_bt_maxkey(dbp, bt_maxkey)
DB *dbp;
u_int32_t bt_maxkey;
{
BTREE *t;
DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_maxkey");
DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE);
t = dbp->bt_internal;
if (bt_maxkey < 1) {
__db_err(dbp->dbenv, "minimum bt_maxkey value is 1");
return (EINVAL);
}
t->bt_maxkey = bt_maxkey;
return (0);
}
/* /*
* __db_get_bt_minkey -- * __db_get_bt_minkey --
* Get the minimum keys per page. * Get the minimum keys per page.

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_open.c,v 11.92 2004/04/29 14:39:47 ubell Exp $ * $Id: bt_open.c,v 12.5 2005/09/28 17:44:17 margo Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -311,7 +311,6 @@ __bam_read_root(dbp, txn, base_pgno, flags)
* metadata page will be created/initialized elsewhere. * metadata page will be created/initialized elsewhere.
*/ */
if (meta->dbmeta.magic == DB_BTREEMAGIC) { if (meta->dbmeta.magic == DB_BTREEMAGIC) {
t->bt_maxkey = meta->maxkey;
t->bt_minkey = meta->minkey; t->bt_minkey = meta->minkey;
t->re_pad = (int)meta->re_pad; t->re_pad = (int)meta->re_pad;
t->re_len = meta->re_len; t->re_len = meta->re_len;
@ -395,7 +394,6 @@ __bam_init_meta(dbp, meta, pgno, lsnp)
memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN); memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN);
t = dbp->bt_internal; t = dbp->bt_internal;
meta->maxkey = t->bt_maxkey;
meta->minkey = t->bt_minkey; meta->minkey = t->bt_minkey;
meta->re_len = t->re_len; meta->re_len = t->re_len;
meta->re_pad = (u_int32_t)t->re_pad; meta->re_pad = (u_int32_t)t->re_pad;
@ -428,7 +426,7 @@ __bam_new_file(dbp, txn, fhp, name)
DBT pdbt; DBT pdbt;
PAGE *root; PAGE *root;
db_pgno_t pgno; db_pgno_t pgno;
int ret; int ret, t_ret;
void *buf; void *buf;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -437,7 +435,7 @@ __bam_new_file(dbp, txn, fhp, name)
meta = NULL; meta = NULL;
buf = NULL; buf = NULL;
if (name == NULL) { if (F_ISSET(dbp, DB_AM_INMEM)) {
/* Build the meta-data page. */ /* Build the meta-data page. */
pgno = PGNO_BASE_MD; pgno = PGNO_BASE_MD;
if ((ret = if ((ret =
@ -447,6 +445,9 @@ __bam_new_file(dbp, txn, fhp, name)
__bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn); __bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn);
meta->root = 1; meta->root = 1;
meta->dbmeta.last_pgno = 1; meta->dbmeta.last_pgno = 1;
if ((ret =
__db_log_page(dbp, txn, &lsn, pgno, (PAGE *)meta)) != 0)
goto err;
ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY); ret = __memp_fput(mpf, meta, DB_MPOOL_DIRTY);
meta = NULL; meta = NULL;
if (ret != 0) if (ret != 0)
@ -460,6 +461,9 @@ __bam_new_file(dbp, txn, fhp, name)
P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID, P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID,
LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE); LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE);
LSN_NOT_LOGGED(root->lsn); LSN_NOT_LOGGED(root->lsn);
if ((ret =
__db_log_page(dbp, txn, &root->lsn, pgno, root)) != 0)
goto err;
ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY); ret = __memp_fput(mpf, root, DB_MPOOL_DIRTY);
root = NULL; root = NULL;
if (ret != 0) if (ret != 0)
@ -509,10 +513,12 @@ __bam_new_file(dbp, txn, fhp, name)
err: if (buf != NULL) err: if (buf != NULL)
__os_free(dbenv, buf); __os_free(dbenv, buf);
else { else {
if (meta != NULL) if (meta != NULL &&
(void)__memp_fput(mpf, meta, 0); (t_ret = __memp_fput(mpf, meta, 0)) != 0 && ret == 0)
if (root != NULL) ret = t_ret;
(void)__memp_fput(mpf, root, 0); if (root != NULL &&
(t_ret = __memp_fput(mpf, root, 0)) != 0 && ret == 0)
ret = t_ret;
} }
return (ret); return (ret);
} }

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_put.c,v 11.80 2004/10/29 17:33:25 ubell Exp $ * $Id: bt_put.c,v 12.10 2005/10/20 18:57:00 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -58,7 +58,9 @@
static int __bam_build static int __bam_build
__P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t)); __P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t));
static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t)); static int __bam_dup_check __P((DBC *, u_int32_t,
PAGE *, u_int32_t, u_int32_t, db_indx_t *));
static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t, u_int32_t));
static int __bam_ovput static int __bam_ovput
__P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *)); __P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *));
static u_int32_t static u_int32_t
@ -84,11 +86,12 @@ __bam_iitem(dbc, key, data, op, flags)
DBT bk_hdr, tdbt; DBT bk_hdr, tdbt;
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *h; PAGE *h;
db_indx_t indx; db_indx_t cnt, indx;
u_int32_t data_size, have_bytes, need_bytes, needed; u_int32_t data_size, have_bytes, need_bytes, needed, pages, pagespace;
int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted; int cmp, bigkey, bigdata, dupadjust, padrec, replace, ret, was_deleted;
COMPQUIET(bk, NULL); COMPQUIET(bk, NULL);
COMPQUIET(cnt, 0);
dbp = dbc->dbp; dbp = dbc->dbp;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
@ -217,13 +220,39 @@ __bam_iitem(dbc, key, data, op, flags)
return (__db_unknown_flag(dbenv, "DB->put", op)); return (__db_unknown_flag(dbenv, "DB->put", op));
} }
/* /* Split the page if there's not enough room. */
* If there's not enough room, or the user has put a ceiling on the
* number of keys permitted in the page, split the page.
*/
if (P_FREESPACE(dbp, h) < needed) if (P_FREESPACE(dbp, h) < needed)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
/*
* Check to see if we will convert to off page duplicates -- if
* so, we'll need a page.
*/
if (F_ISSET(dbp, DB_AM_DUP) &&
TYPE(h) == P_LBTREE && op != DB_KEYFIRST &&
P_FREESPACE(dbp, h) - needed <= dbp->pgsize / 2 &&
__bam_dup_check(dbc, op, h, indx, needed, &cnt)) {
pages = 1;
dupadjust = 1;
} else
pages = 0;
/*
* If we are not using transactions and there is a page limit
* set on the file, then figure out if things will fit before
* taking action.
*/
if (dbc->txn == NULL && dbp->mpf->mfp->maxpgno != 0) {
pagespace = P_MAXSPACE(dbp, dbp->pgsize);
if (bigdata)
pages += ((data_size - 1) / pagespace) + 1;
if (bigkey)
pages += ((key->size - 1) / pagespace) + 1;
if (pages > (dbp->mpf->mfp->maxpgno - dbp->mpf->mfp->last_pgno))
return (__db_space_err(dbp));
}
/* /*
* The code breaks it up into five cases: * The code breaks it up into five cases:
* *
@ -259,7 +288,6 @@ __bam_iitem(dbc, key, data, op, flags)
return (ret); return (ret);
indx += 3; indx += 3;
dupadjust = 1;
cp->indx += 2; cp->indx += 2;
} else { } else {
@ -276,7 +304,6 @@ __bam_iitem(dbc, key, data, op, flags)
return (ret); return (ret);
++indx; ++indx;
dupadjust = 1;
} }
break; break;
case DB_CURRENT: case DB_CURRENT:
@ -287,11 +314,11 @@ __bam_iitem(dbc, key, data, op, flags)
* will try and remove the item because the cursor's delete * will try and remove the item because the cursor's delete
* flag is set. * flag is set.
*/ */
(void)__bam_ca_delete(dbp, PGNO(h), indx, 0); if ((ret = __bam_ca_delete(dbp, PGNO(h), indx, 0, NULL)) != 0)
return (ret);
if (TYPE(h) == P_LBTREE) { if (TYPE(h) == P_LBTREE) {
++indx; ++indx;
dupadjust = 1;
} }
/* /*
@ -380,10 +407,9 @@ __bam_iitem(dbc, key, data, op, flags)
* up at least 25% of the space on the page. If it does, move it onto * up at least 25% of the space on the page. If it does, move it onto
* its own page. * its own page.
*/ */
if (dupadjust && P_FREESPACE(dbp, h) <= dbp->pgsize / 2) { if (dupadjust &&
if ((ret = __bam_dup_convert(dbc, h, indx - O_INDX)) != 0) (ret = __bam_dup_convert(dbc, h, indx - O_INDX, cnt)) != 0)
return (ret); return (ret);
}
/* If we've modified a recno file, set the flag. */ /* If we've modified a recno file, set the flag. */
if (dbc->dbtype == DB_RECNO) if (dbc->dbtype == DB_RECNO)
@ -664,26 +690,22 @@ __bam_ritem(dbc, h, indx, data)
} }
/* /*
* __bam_dup_convert -- * __bam_dup_check --
* Check to see if the duplicate set at indx should have its own page. * Check to see if the duplicate set at indx should have its own page.
* If it should, create it.
*/ */
static int static int
__bam_dup_convert(dbc, h, indx) __bam_dup_check(dbc, op, h, indx, sz, cntp)
DBC *dbc; DBC *dbc;
u_int32_t op;
PAGE *h; PAGE *h;
u_int32_t indx; u_int32_t indx, sz;
db_indx_t *cntp;
{ {
BKEYDATA *bk; BKEYDATA *bk;
DB *dbp; DB *dbp;
DBT hdr; db_indx_t cnt, first, *inp;
DB_MPOOLFILE *mpf;
PAGE *dp;
db_indx_t cnt, cpindx, dindx, first, *inp, sz;
int ret;
dbp = dbc->dbp; dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h); inp = P_INP(dbp, h);
/* /*
@ -695,11 +717,21 @@ __bam_dup_convert(dbc, h, indx)
/* Count the key once. */ /* Count the key once. */
bk = GET_BKEYDATA(dbp, h, indx); bk = GET_BKEYDATA(dbp, h, indx);
sz = B_TYPE(bk->type) == B_KEYDATA ? sz += B_TYPE(bk->type) == B_KEYDATA ?
BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE;
/* Sum up all the data items. */ /* Sum up all the data items. */
for (cnt = 0, first = indx; first = indx;
/*
* Account for the record being inserted. If we are replacing it,
* don't count it twice.
*
* We execute the loop with first == indx to get the size of the
* first record.
*/
cnt = op == DB_CURRENT ? 0 : 1;
for (first = indx;
indx < NUM_ENT(h) && inp[first] == inp[indx]; indx < NUM_ENT(h) && inp[first] == inp[indx];
++cnt, indx += P_INDX) { ++cnt, indx += P_INDX) {
bk = GET_BKEYDATA(dbp, h, indx + O_INDX); bk = GET_BKEYDATA(dbp, h, indx + O_INDX);
@ -726,6 +758,36 @@ __bam_dup_convert(dbc, h, indx)
if (sz < dbp->pgsize / 4) if (sz < dbp->pgsize / 4)
return (0); return (0);
*cntp = cnt;
return (1);
}
/*
* __bam_dup_convert --
* Move a set of duplicates off-page and into their own tree.
*/
static int
__bam_dup_convert(dbc, h, indx, cnt)
DBC *dbc;
PAGE *h;
u_int32_t indx, cnt;
{
BKEYDATA *bk;
DB *dbp;
DBT hdr;
DB_MPOOLFILE *mpf;
PAGE *dp;
db_indx_t cpindx, dindx, first, *inp;
int ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
inp = P_INP(dbp, h);
/* Move to the beginning of the dup set. */
while (indx > 0 && inp[indx] == inp[indx - P_INDX])
indx -= P_INDX;
/* Get a new page. */ /* Get a new page. */
if ((ret = __db_new(dbc, if ((ret = __db_new(dbc,
dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0) dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &dp)) != 0)
@ -739,8 +801,8 @@ __bam_dup_convert(dbc, h, indx)
* we're dealing with. * we're dealing with.
*/ */
memset(&hdr, 0, sizeof(hdr)); memset(&hdr, 0, sizeof(hdr));
dindx = first; first = indx;
indx = first; dindx = indx;
cpindx = 0; cpindx = 0;
do { do {
/* Move cursors referencing the old entry to the new entry. */ /* Move cursors referencing the old entry to the new entry. */

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_rec.c,v 11.70 2004/09/24 00:43:12 bostic Exp $ * $Id: bt_rec.c,v 12.11 2005/10/20 18:57:01 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -58,7 +58,7 @@ __bam_split_recover(dbenv, dbtp, lsnp, op, info)
_lp = lp = np = pp = _rp = rp = NULL; _lp = lp = np = pp = _rp = rp = NULL;
sp = NULL; sp = NULL;
REC_INTRO(__bam_split_read, 1); REC_INTRO(__bam_split_read, 1, 0);
/* /*
* There are two kinds of splits that we have to recover from. The * There are two kinds of splits that we have to recover from. The
@ -96,21 +96,21 @@ redo: if (DB_REDO(op)) {
REC_FGET(mpf, root_pgno, &pp, do_left); REC_FGET(mpf, root_pgno, &pp, do_left);
cmp = cmp =
log_compare(&LSN(pp), &LSN(argp->pg.data)); log_compare(&LSN(pp), &LSN(argp->pg.data));
CHECK_LSN(op, CHECK_LSN(dbenv, op,
cmp, &LSN(pp), &LSN(argp->pg.data)); cmp, &LSN(pp), &LSN(argp->pg.data));
p_update = cmp == 0; p_update = cmp == 0;
} }
do_left: if (lp != NULL) { do_left: if (lp != NULL) {
cmp = log_compare(&LSN(lp), &argp->llsn); cmp = log_compare(&LSN(lp), &argp->llsn);
CHECK_LSN(op, cmp, &LSN(lp), &argp->llsn); CHECK_LSN(dbenv, op, cmp, &LSN(lp), &argp->llsn);
if (cmp == 0) if (cmp == 0)
l_update = 1; l_update = 1;
} }
if (rp != NULL) { if (rp != NULL) {
cmp = log_compare(&LSN(rp), &argp->rlsn); cmp = log_compare(&LSN(rp), &argp->rlsn);
CHECK_LSN(op, cmp, &LSN(rp), &argp->rlsn); CHECK_LSN(dbenv, op, cmp, &LSN(rp), &argp->rlsn);
if (cmp == 0) if (cmp == 0)
r_update = 1; r_update = 1;
} }
@ -211,7 +211,7 @@ check_next: /*
goto done; goto done;
} }
cmp = log_compare(&LSN(np), &argp->nlsn); cmp = log_compare(&LSN(np), &argp->nlsn);
CHECK_LSN(op, cmp, &LSN(np), &argp->nlsn); CHECK_LSN(dbenv, op, cmp, &LSN(np), &argp->nlsn);
if (cmp == 0) { if (cmp == 0) {
PREV_PGNO(np) = argp->right; PREV_PGNO(np) = argp->right;
np->lsn = *lsnp; np->lsn = *lsnp;
@ -337,12 +337,13 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
DB_MPOOLFILE *mpf; DB_MPOOLFILE *mpf;
PAGE *pagep; PAGE *pagep;
db_pgno_t pgno, root_pgno; db_pgno_t pgno, root_pgno;
db_recno_t rcnt;
int cmp_n, cmp_p, modified, ret; int cmp_n, cmp_p, modified, ret;
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_rsplit_print); REC_PRINT(__bam_rsplit_print);
REC_INTRO(__bam_rsplit_read, 1); REC_INTRO(__bam_rsplit_read, 1, 1);
/* Fix the root page. */ /* Fix the root page. */
pgno = root_pgno = argp->root_pgno; pgno = root_pgno = argp->root_pgno;
@ -361,10 +362,19 @@ __bam_rsplit_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->rootlsn); cmp_p = log_compare(&LSN(pagep), &argp->rootlsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->rootlsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->rootlsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /*
* Copy the new data to the root page. If it is not now a
* leaf page we need to restore the record number. We could
* try to determine if C_RECNUM was set in the btree, but
* that's not really necessary since the field is not used
* otherwise.
*/
rcnt = RE_NREC(pagep);
memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size); memcpy(pagep, argp->pgdbt.data, argp->pgdbt.size);
if (LEVEL(pagep) > LEAFLEVEL)
RE_NREC_SET(pagep, rcnt);
pagep->pgno = root_pgno; pagep->pgno = root_pgno;
pagep->lsn = *lsnp; pagep->lsn = *lsnp;
modified = 1; modified = 1;
@ -403,7 +413,7 @@ do_page:
(void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN)); (void)__ua_memcpy(&copy_lsn, &LSN(argp->pgdbt.data), sizeof(DB_LSN));
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &copy_lsn); cmp_p = log_compare(&LSN(pagep), &copy_lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &copy_lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &copy_lsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
pagep->lsn = *lsnp; pagep->lsn = *lsnp;
@ -450,7 +460,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_adj_print); REC_PRINT(__bam_adj_print);
REC_INTRO(__bam_adj_read, 1); REC_INTRO(__bam_adj_read, 1, 1);
/* Get the page; if it never existed and we're undoing, we're done. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -468,7 +478,7 @@ __bam_adj_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
if ((ret = __bam_adjindx(dbc, if ((ret = __bam_adjindx(dbc,
@ -524,7 +534,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_cadjust_print); REC_PRINT(__bam_cadjust_print);
REC_INTRO(__bam_cadjust_read, 1); REC_INTRO(__bam_cadjust_read, 1, 0);
/* Get the page; if it never existed and we're undoing, we're done. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -542,7 +552,7 @@ __bam_cadjust_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
if (IS_BTREE_PAGE(pagep)) { if (IS_BTREE_PAGE(pagep)) {
@ -613,7 +623,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_cdel_print); REC_PRINT(__bam_cdel_print);
REC_INTRO(__bam_cdel_read, 1); REC_INTRO(__bam_cdel_read, 1, 0);
/* Get the page; if it never existed and we're undoing, we're done. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -631,7 +641,7 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0); indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
@ -644,7 +654,9 @@ __bam_cdel_recover(dbenv, dbtp, lsnp, op, info)
indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0); indx = argp->indx + (TYPE(pagep) == P_LBTREE ? O_INDX : 0);
B_DCLR(GET_BKEYDATA(file_dbp, pagep, indx)->type); B_DCLR(GET_BKEYDATA(file_dbp, pagep, indx)->type);
(void)__bam_ca_delete(file_dbp, argp->pgno, argp->indx, 0); if ((ret = __bam_ca_delete(
file_dbp, argp->pgno, argp->indx, 0, NULL)) != 0)
goto out;
LSN(pagep) = argp->lsn; LSN(pagep) = argp->lsn;
modified = 1; modified = 1;
@ -689,7 +701,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_repl_print); REC_PRINT(__bam_repl_print);
REC_INTRO(__bam_repl_read, 1); REC_INTRO(__bam_repl_read, 1, 1);
/* Get the page; if it never existed and we're undoing, we're done. */ /* Get the page; if it never existed and we're undoing, we're done. */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
@ -708,7 +720,7 @@ __bam_repl_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn); cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* /*
* Need to redo update described. * Need to redo update described.
@ -799,7 +811,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
meta = NULL; meta = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_root_print); REC_PRINT(__bam_root_print);
REC_INTRO(__bam_root_read, 0); REC_INTRO(__bam_root_read, 0, 0);
if ((ret = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) { if ((ret = __memp_fget(mpf, &argp->meta_pgno, 0, &meta)) != 0) {
if (ret != DB_PAGE_NOTFOUND if (ret != DB_PAGE_NOTFOUND
@ -816,7 +828,7 @@ __bam_root_recover(dbenv, dbtp, lsnp, op, info)
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(meta)); cmp_n = log_compare(lsnp, &LSN(meta));
cmp_p = log_compare(&LSN(meta), &argp->meta_lsn); cmp_p = log_compare(&LSN(meta), &argp->meta_lsn);
CHECK_LSN(op, cmp_p, &LSN(meta), &argp->meta_lsn); CHECK_LSN(dbenv, op, cmp_p, &LSN(meta), &argp->meta_lsn);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Need to redo update described. */ /* Need to redo update described. */
meta->root = argp->root_pgno; meta->root = argp->root_pgno;
@ -866,7 +878,7 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
COMPQUIET(mpf, NULL); COMPQUIET(mpf, NULL);
REC_PRINT(__bam_curadj_print); REC_PRINT(__bam_curadj_print);
REC_INTRO(__bam_curadj_read, 0); REC_INTRO(__bam_curadj_read, 0, 1);
ret = 0; ret = 0;
if (op != DB_TXN_ABORT) if (op != DB_TXN_ABORT)
@ -891,8 +903,9 @@ __bam_curadj_recover(dbenv, dbtp, lsnp, op, info)
break; break;
case DB_CA_SPLIT: case DB_CA_SPLIT:
__bam_ca_undosplit(file_dbp, argp->from_pgno, if ((ret = __bam_ca_undosplit(file_dbp, argp->from_pgno,
argp->to_pgno, argp->left_pgno, argp->from_indx); argp->to_pgno, argp->left_pgno, argp->from_indx)) != 0)
goto out;
break; break;
} }
@ -928,7 +941,7 @@ __bam_rcuradj_recover(dbenv, dbtp, lsnp, op, info)
rdbc = NULL; rdbc = NULL;
REC_PRINT(__bam_rcuradj_print); REC_PRINT(__bam_rcuradj_print);
REC_INTRO(__bam_rcuradj_read, 0); REC_INTRO(__bam_rcuradj_read, 0, 1);
ret = t_ret = 0; ret = t_ret = 0;
@ -1008,7 +1021,7 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info)
pagep = NULL; pagep = NULL;
COMPQUIET(info, NULL); COMPQUIET(info, NULL);
REC_PRINT(__bam_relink_print); REC_PRINT(__bam_relink_print);
REC_INTRO(__bam_relink_read, 1); REC_INTRO(__bam_relink_read, 1, 0);
/* /*
* There are up to three pages we need to check -- the page, and the * There are up to three pages we need to check -- the page, and the
@ -1016,38 +1029,7 @@ __bam_relink_recover(dbenv, dbtp, lsnp, op, info)
* the current page is the result of a split and is being recovered * the current page is the result of a split and is being recovered
* elsewhere, so all we need do is recover the next page. * elsewhere, so all we need do is recover the next page.
*/ */
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) { if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE
|| DB_REDO(op)
#endif
) {
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
} else
goto next2;
}
modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the relink. */
pagep->lsn = *lsnp;
modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
/* Undo the relink. */
pagep->next_pgno = argp->next;
pagep->prev_pgno = argp->prev;
pagep->lsn = argp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
pagep = NULL;
next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE #ifndef HAVE_FTRUNCATE
|| DB_REDO(op) || DB_REDO(op)
@ -1062,24 +1044,24 @@ next2: if ((ret = __memp_fget(mpf, &argp->next, 0, &pagep)) != 0) {
modified = 0; modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep)); cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn_next); cmp_p = log_compare(&LSN(pagep), &argp->lsn_next);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_next); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_next);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the remove or undo the add. */ /* Redo the remove or replace. */
pagep->prev_pgno = argp->prev; if (argp->new_pgno == PGNO_INVALID)
pagep->prev_pgno = argp->prev;
else
pagep->prev_pgno = argp->new_pgno;
pagep->lsn = *lsnp;
modified = 1; modified = 1;
} else if (cmp_n == 0 && DB_UNDO(op)) { } else if (cmp_n == 0 && DB_UNDO(op)) {
/* Undo the remove or redo the add. */ /* Undo the remove or replace. */
pagep->prev_pgno = argp->pgno; pagep->prev_pgno = argp->pgno;
pagep->lsn = argp->lsn_next;
modified = 1; modified = 1;
} }
if (modified == 1) {
if (DB_UNDO(op))
pagep->lsn = argp->lsn_next;
else
pagep->lsn = *lsnp;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out; goto out;
pagep = NULL; pagep = NULL;
@ -1098,24 +1080,24 @@ prev: if ((ret = __memp_fget(mpf, &argp->prev, 0, &pagep)) != 0) {
modified = 0; modified = 0;
cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev); cmp_p = log_compare(&LSN(pagep), &argp->lsn_prev);
CHECK_LSN(op, cmp_p, &LSN(pagep), &argp->lsn_prev); CHECK_LSN(dbenv, op, cmp_p, &LSN(pagep), &argp->lsn_prev);
if (cmp_p == 0 && DB_REDO(op)) { if (cmp_p == 0 && DB_REDO(op)) {
/* Redo the relink. */ /* Redo the relink. */
pagep->next_pgno = argp->next; if (argp->new_pgno == PGNO_INVALID)
pagep->next_pgno = argp->next;
else
pagep->next_pgno = argp->new_pgno;
pagep->lsn = *lsnp;
modified = 1; modified = 1;
} else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) { } else if (log_compare(lsnp, &LSN(pagep)) == 0 && DB_UNDO(op)) {
/* Undo the relink. */ /* Undo the relink. */
pagep->next_pgno = argp->pgno; pagep->next_pgno = argp->pgno;
pagep->lsn = argp->lsn_prev;
modified = 1; modified = 1;
} }
if (modified == 1) {
if (DB_UNDO(op))
pagep->lsn = argp->lsn_prev;
else
pagep->lsn = *lsnp;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0) if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out; goto out;
pagep = NULL; pagep = NULL;
@ -1127,3 +1109,281 @@ out: if (pagep != NULL)
(void)__memp_fput(mpf, pagep, 0); (void)__memp_fput(mpf, pagep, 0);
REC_CLOSE; REC_CLOSE;
} }
/*
* __bam_merge_recover --
* Recovery function for merge.
*
* PUBLIC: int __bam_merge_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__bam_merge_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
__bam_merge_args *argp;
BKEYDATA *bk;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep;
db_indx_t indx, *ninp, *pinp;
u_int32_t size;
u_int8_t *bp;
int cmp_n, cmp_p, i, modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__bam_merge_print);
REC_INTRO(__bam_merge_read, 1, 1);
if ((ret = __memp_fget(mpf, &argp->pgno, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE
|| DB_REDO(op)
#endif
) {
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
} else
goto next;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if (cmp_p == 0 && DB_REDO(op)) {
/*
* If the header is provided the page is empty, copy the
* needed data.
*/
DB_ASSERT(argp->hdr.size == 0 || NUM_ENT(pagep) == 0);
if (argp->hdr.size != 0) {
P_INIT(pagep, file_dbp->pgsize, pagep->pgno,
PREV_PGNO(argp->hdr.data),
NEXT_PGNO(argp->hdr.data),
LEVEL(argp->hdr.data), TYPE(argp->hdr.data));
}
if (TYPE(pagep) == P_OVERFLOW) {
OV_REF(pagep) = OV_REF(argp->hdr.data);
OV_LEN(pagep) = OV_LEN(argp->hdr.data);
bp = (u_int8_t *) pagep + P_OVERHEAD(file_dbp);
memcpy(bp, argp->data.data, argp->data.size);
} else {
/* Copy the data segment. */
bp = (u_int8_t *)pagep +
(db_indx_t)(HOFFSET(pagep) - argp->data.size);
memcpy(bp, argp->data.data, argp->data.size);
/* Copy index table offset past the current entries. */
pinp = P_INP(file_dbp, pagep) + NUM_ENT(pagep);
ninp = argp->ind.data;
for (i = 0;
i < (int)(argp->ind.size / sizeof(*ninp)); i++)
*pinp++ = *ninp++
- (file_dbp->pgsize - HOFFSET(pagep));
HOFFSET(pagep) -= argp->data.size;
NUM_ENT(pagep) += i;
}
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && !DB_REDO(op)) {
/*
* Since logging is logical at the page level
* we cannot just truncate the data space. Delete
* the proper number of items from the logical end
* of the page.
*/
for (i = 0; i < (int)(argp->ind.size / sizeof(*ninp)); i++) {
indx = NUM_ENT(pagep) - 1;
if (P_INP(file_dbp, pagep)[indx] ==
P_INP(file_dbp, pagep)[indx - P_INDX]) {
NUM_ENT(pagep)--;
continue;
}
switch (TYPE(pagep)) {
case P_LBTREE:
case P_LRECNO:
case P_LDUP:
bk = GET_BKEYDATA(file_dbp, pagep, indx);
size = BITEM_SIZE(bk);
break;
case P_IBTREE:
size = BINTERNAL_SIZE(
GET_BINTERNAL(file_dbp, pagep, indx)->len);
break;
case P_IRECNO:
size = RINTERNAL_SIZE;
break;
default:
ret = __db_pgfmt(dbenv, PGNO(pagep));
goto out;
}
if ((ret =
__db_ditem(dbc, pagep, indx, size)) != 0)
goto out;
}
if (argp->ind.size == 0)
HOFFSET(pagep) = file_dbp->pgsize;
pagep->lsn = argp->lsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
next: if ((ret = __memp_fget(mpf, &argp->npgno, 0, &pagep)) != 0) {
if (ret != DB_PAGE_NOTFOUND
#ifndef HAVE_FTRUNCATE
|| DB_REDO(op)
#endif
) {
ret = __db_pgerr(file_dbp, argp->pgno, ret);
goto out;
} else
goto done;
}
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->nlsn);
CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->nlsn);
if (cmp_p == 0 && DB_REDO(op)) {
/* Need to truncate the page. */
HOFFSET(pagep) = file_dbp->pgsize;
NUM_ENT(pagep) = 0;
pagep->lsn = *lsnp;
modified = 1;
} else if (cmp_n == 0 && !DB_REDO(op)) {
/* Need to put the data back on the page. */
if (TYPE(pagep) == P_OVERFLOW) {
OV_REF(pagep) = OV_REF(argp->hdr.data);
OV_LEN(pagep) = OV_LEN(argp->hdr.data);
bp = (u_int8_t *) pagep + P_OVERHEAD(file_dbp);
memcpy(bp, argp->data.data, argp->data.size);
} else {
bp = (u_int8_t *)pagep +
(db_indx_t)(HOFFSET(pagep) - argp->data.size);
memcpy(bp, argp->data.data, argp->data.size);
/* Copy index table. */
pinp = P_INP(file_dbp, pagep) + NUM_ENT(pagep);
ninp = argp->ind.data;
for (i = 0;
i < (int)(argp->ind.size / sizeof(*ninp)); i++)
*pinp++ = *ninp++;
HOFFSET(pagep) -= argp->data.size;
NUM_ENT(pagep) = i;
}
pagep->lsn = argp->nlsn;
modified = 1;
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done:
*lsnp = argp->prev_lsn;
ret = 0;
out: REC_CLOSE;
}
/*
* __bam_pgno_recover --
* Recovery function for page number replacment.
*
* PUBLIC: int __bam_pgno_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
__bam_pgno_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
BINTERNAL *bi;
__bam_pgno_args *argp;
DB *file_dbp;
DBC *dbc;
DB_MPOOLFILE *mpf;
PAGE *pagep, *npagep;
db_pgno_t *pgnop;
int cmp_n, cmp_p, modified, ret;
COMPQUIET(info, NULL);
REC_PRINT(__bam_pgno_print);
REC_INTRO(__bam_pgno_read, 1, 0);
REC_FGET(mpf, argp->pgno, &pagep, done);
modified = 0;
cmp_n = log_compare(lsnp, &LSN(pagep));
cmp_p = log_compare(&LSN(pagep), &argp->lsn);
CHECK_LSN(file_dbp->dbenv, op, cmp_p, &LSN(pagep), &argp->lsn);
if ((cmp_p == 0 && DB_REDO(op)) || (cmp_n == 0 && !DB_REDO(op))) {
switch (TYPE(pagep)) {
case P_IBTREE:
/*
* An internal record can have both a overflow
* and child pointer. Fetch the page to see
* which it is.
*/
bi = GET_BINTERNAL(file_dbp, pagep, argp->indx);
if (B_TYPE(bi->type) == B_OVERFLOW) {
REC_FGET(mpf, argp->npgno, &npagep, out);
if (TYPE(npagep) == P_OVERFLOW)
pgnop =
&((BOVERFLOW *)(bi->data))->pgno;
else
pgnop = &bi->pgno;
if ((ret = __memp_fput(mpf, npagep, 0)) != 0)
goto out;
break;
}
pgnop = &bi->pgno;
break;
case P_IRECNO:
pgnop =
&GET_RINTERNAL(file_dbp, pagep, argp->indx)->pgno;
break;
default:
pgnop =
&GET_BOVERFLOW(file_dbp, pagep, argp->indx)->pgno;
break;
}
if (DB_REDO(op)) {
/* Need to redo update described. */
*pgnop = argp->npgno;
pagep->lsn = *lsnp;
modified = 1;
} else {
*pgnop = argp->opgno;
pagep->lsn = argp->lsn;
modified = 1;
}
}
if ((ret = __memp_fput(mpf, pagep, modified ? DB_MPOOL_DIRTY : 0)) != 0)
goto out;
done:
*lsnp = argp->prev_lsn;
ret = 0;
out: REC_CLOSE;
}

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1998-2004 * Copyright (c) 1998-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_reclaim.c,v 11.15 2004/01/28 03:35:49 bostic Exp $ * $Id: bt_reclaim.c,v 12.2 2005/06/16 20:20:19 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -69,7 +69,8 @@ __bam_truncate(dbc, countp)
ret = __bam_traverse(dbc, ret = __bam_traverse(dbc,
DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc); DB_LOCK_WRITE, dbc->internal->root, __db_truncate_callback, &trunc);
*countp = trunc.count; if (countp != NULL)
*countp = trunc.count;
return (ret); return (ret);
} }

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1997-2004 * Copyright (c) 1997-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_recno.c,v 11.117 2004/03/28 17:01:01 bostic Exp $ * $Id: bt_recno.c,v 12.6 2005/08/08 14:27:59 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -203,7 +203,6 @@ __ram_c_del(dbc)
DB *dbp; DB *dbp;
DB_LSN lsn; DB_LSN lsn;
DBT hdr, data; DBT hdr, data;
EPG *epg;
int exact, ret, stack, t_ret; int exact, ret, stack, t_ret;
dbp = dbc->dbp; dbp = dbc->dbp;
@ -280,21 +279,11 @@ __ram_c_del(dbc)
* are closed, and then clean it up. * are closed, and then clean it up.
*/ */
if (NUM_ENT(cp->page) == 0 && PGNO(cp->page) != cp->root) { if (NUM_ENT(cp->page) == 0 && PGNO(cp->page) != cp->root) {
/*
* We already have a locked stack of pages. However,
* there are likely entries in the stack that aren't
* going to be emptied by removing the single reference
* to the emptied page (or one of its parents).
*/
for (epg = cp->csp; epg >= cp->sp; --epg)
if (NUM_ENT(epg->page) > 1)
break;
/* /*
* We want to delete a single item out of the last page * We want to delete a single item out of the last page
* that we're not deleting. * that we're not deleting.
*/ */
ret = __bam_dpages(dbc, epg); ret = __bam_dpages(dbc, 0, 0);
/* /*
* Regardless of the return from __bam_dpages, it will * Regardless of the return from __bam_dpages, it will
@ -764,7 +753,7 @@ __ram_ca(dbc_arg, op)
*/ */
DB_ASSERT(F_ISSET(cp_arg, C_RENUMBER)); DB_ASSERT(F_ISSET(cp_arg, C_RENUMBER));
MUTEX_THREAD_LOCK(dbenv, dbenv->dblist_mutexp); MUTEX_LOCK(dbenv, dbenv->mtx_dblist);
/* /*
* Adjust the cursors. See the comment in __bam_ca_delete(). * Adjust the cursors. See the comment in __bam_ca_delete().
*/ */
@ -780,7 +769,7 @@ __ram_ca(dbc_arg, op)
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
@ -789,7 +778,7 @@ __ram_ca(dbc_arg, op)
order <= cp->order) order <= cp->order)
order = cp->order + 1; order = cp->order + 1;
} }
MUTEX_THREAD_UNLOCK(dbenv, dbp->mutexp); MUTEX_UNLOCK(dbenv, dbp->mutex);
} }
} else } else
order = INVALID_ORDER; order = INVALID_ORDER;
@ -798,7 +787,7 @@ __ram_ca(dbc_arg, op)
for (ldbp = __dblist_get(dbenv, dbp->adj_fileid); for (ldbp = __dblist_get(dbenv, dbp->adj_fileid);
ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid;
ldbp = LIST_NEXT(ldbp, dblistlinks)) { ldbp = LIST_NEXT(ldbp, dblistlinks)) {
MUTEX_THREAD_LOCK(dbenv, dbp->mutexp); MUTEX_LOCK(dbenv, dbp->mutex);
for (dbc = TAILQ_FIRST(&ldbp->active_queue); for (dbc = TAILQ_FIRST(&ldbp->active_queue);
dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) { dbc != NULL; dbc = TAILQ_NEXT(dbc, links)) {
cp = (BTREE_CURSOR *)dbc->internal; cp = (BTREE_CURSOR *)dbc->internal;
@ -868,9 +857,9 @@ iafter: if (!adjusted && C_LESSTHAN(cp_arg, cp)) {
break; break;
} }
} }
MUTEX_THREAD_UNLOCK(dbp->dbenv, dbp->mutexp); MUTEX_UNLOCK(dbp->dbenv, dbp->mutex);
} }
MUTEX_THREAD_UNLOCK(dbenv, dbenv->dblist_mutexp); MUTEX_UNLOCK(dbenv, dbenv->mtx_dblist);
return (found); return (found);
} }
@ -1037,6 +1026,18 @@ __ram_writeback(dbp)
return (0); return (0);
} }
/*
* We step through the records, writing each one out. Use the record
* number and the dbp->get() function, instead of a cursor, so we find
* and write out "deleted" or non-existent records. The DB handle may
* be threaded, so allocate memory as we go.
*/
memset(&key, 0, sizeof(key));
key.size = sizeof(db_recno_t);
key.data = &keyno;
memset(&data, 0, sizeof(data));
F_SET(&data, DB_DBT_REALLOC);
/* Allocate a cursor. */ /* Allocate a cursor. */
if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0) if ((ret = __db_cursor(dbp, NULL, &dbc, 0)) != 0)
return (ret); return (ret);
@ -1064,7 +1065,7 @@ __ram_writeback(dbp)
*/ */
if ((ret = if ((ret =
__ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND) __ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND)
return (ret); goto err;
/* /*
* Close any existing file handle and re-open the file, truncating it. * Close any existing file handle and re-open the file, truncating it.
@ -1082,18 +1083,6 @@ __ram_writeback(dbp)
goto err; goto err;
} }
/*
* We step through the records, writing each one out. Use the record
* number and the dbp->get() function, instead of a cursor, so we find
* and write out "deleted" or non-existent records. The DB handle may
* be threaded, so allocate memory as we go.
*/
memset(&key, 0, sizeof(key));
key.size = sizeof(db_recno_t);
key.data = &keyno;
memset(&data, 0, sizeof(data));
F_SET(&data, DB_DBT_REALLOC);
/* /*
* We'll need the delimiter if we're doing variable-length records, * We'll need the delimiter if we're doing variable-length records,
* and the pad character if we're doing fixed-length records. * and the pad character if we're doing fixed-length records.

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_rsearch.c,v 11.40 2004/07/23 17:21:09 bostic Exp $ * $Id: bt_rsearch.c,v 12.5 2005/08/08 03:37:05 ubell Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -100,44 +100,14 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* *
* Retrieve the root page. * Retrieve the root page.
*/ */
pg = cp->root;
stack = LF_ISSET(S_STACK) ? 1 : 0;
lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
/* if ((ret = __bam_get_root(dbc, cp->root, stop, flags, &stack)) != 0)
* Decide if we need to save this page; if we do, write lock it. return (ret);
* We deliberately don't lock-couple on this call. If the tree lock_mode = cp->csp->lock_mode;
* is tiny, i.e., one page, and two threads are busily updating lock = cp->csp->lock;
* the root page, we're almost guaranteed deadlocks galore, as h = cp->csp->page;
* each one gets a read lock and then blocks the other's attempt
* for a write lock.
*/
if (!stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
stack = 1;
}
BT_STK_CLR(cp);
/* /*
* If appending to the tree, set the record number now -- we have the * If appending to the tree, set the record number now -- we have the
* root page locked. * root page locked.
@ -260,15 +230,15 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
} }
--indx; --indx;
/* Return if this is the lowest page wanted. */
if (stop == LEVEL(h)) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
if (stack) { if (stack) {
/* Return if this is the lowest page wanted. */
if (LF_ISSET(S_PARENT) && stop == h->level) {
BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
return (0);
}
BT_STK_PUSH(dbp->dbenv, BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret); cp, h, indx, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
@ -286,8 +256,8 @@ __bam_rsearch(dbc, recnop, flags, stop, exactp)
* never unlock it. * never unlock it.
*/ */
if ((LF_ISSET(S_PARENT) && if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || (u_int8_t)(stop + 1) >= (u_int8_t)(LEVEL(h) - 1)) ||
(h->level - 1) == LEAFLEVEL) (LEVEL(h) - 1) == LEAFLEVEL)
stack = 1; stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0) if ((ret = __memp_fput(mpf, h, 0)) != 0)

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -39,7 +39,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_search.c,v 11.50 2004/07/23 17:21:09 bostic Exp $ * $Id: bt_search.c,v 12.17 2005/11/10 21:17:13 ubell Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -57,6 +57,102 @@
#include "dbinc/lock.h" #include "dbinc/lock.h"
#include "dbinc/mp.h" #include "dbinc/mp.h"
/*
* __bam_get_root --
* Fetch the root of a tree and see if we want to keep
* it in the stack.
*
* PUBLIC: int __bam_get_root __P((DBC *, db_pgno_t, int, u_int32_t, int *));
*/
int
__bam_get_root(dbc, pg, slevel, flags, stack)
DBC *dbc;
db_pgno_t pg;
int slevel;
u_int32_t flags;
int *stack;
{
BTREE_CURSOR *cp;
DB *dbp;
DB_LOCK lock;
DB_MPOOLFILE *mpf;
PAGE *h;
db_lockmode_t lock_mode;
int ret, t_ret;
dbp = dbc->dbp;
mpf = dbp->mpf;
cp = (BTREE_CURSOR *)dbc->internal;
/*
* If write-locking pages, we need to know whether or not to acquire a
* write lock on a page before getting it. This depends on how deep it
* is in tree, which we don't know until we acquire the root page. So,
* if we need to lock the root page we may have to upgrade it later,
* because we won't get the correct lock initially.
*
* Retrieve the root page.
*/
try_again:
*stack = LF_ISSET(S_STACK) &&
(dbc->dbtype == DB_RECNO || F_ISSET(cp, C_RECNUM));
lock_mode = DB_LOCK_READ;
if (*stack ||
LF_ISSET(S_DEL) || (LF_ISSET(S_NEXT) && LF_ISSET(S_WRITE)))
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
/*
* Decide if we need to save this page; if we do, write lock it.
* We deliberately don't lock-couple on this call. If the tree
* is tiny, i.e., one page, and two threads are busily updating
* the root page, we're almost guaranteed deadlocks galore, as
* each one gets a read lock and then blocks the other's attempt
* for a write lock.
*/
if (!*stack &&
((LF_ISSET(S_PARENT) && (u_int8_t)(slevel + 1) >= LEVEL(h)) ||
(LF_ISSET(S_WRITE) && LEVEL(h) == LEAFLEVEL) ||
(LF_ISSET(S_START) && slevel == LEVEL(h)))) {
if (!STD_LOCKING(dbc))
goto no_relock;
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
if (!((LF_ISSET(S_PARENT) &&
(u_int8_t)(slevel + 1) >= LEVEL(h)) ||
(LF_ISSET(S_WRITE) && LEVEL(h) == LEAFLEVEL) ||
(LF_ISSET(S_START) && slevel == LEVEL(h)))) {
/* Someone else split the root, start over. */
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
goto try_again;
}
no_relock: *stack = 1;
}
BT_STK_ENTER(dbp->dbenv, cp, h, 0, lock, lock_mode, ret);
return (ret);
}
/* /*
* __bam_search -- * __bam_search --
* Search a btree for a key. * Search a btree for a key.
@ -65,12 +161,12 @@
* PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *)); * PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *));
*/ */
int int
__bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp) __bam_search(dbc, root_pgno, key, flags, slevel, recnop, exactp)
DBC *dbc; DBC *dbc;
db_pgno_t root_pgno; db_pgno_t root_pgno;
const DBT *key; const DBT *key;
u_int32_t flags; u_int32_t flags;
int stop, *exactp; int slevel, *exactp;
db_recno_t *recnop; db_recno_t *recnop;
{ {
BTREE *t; BTREE *t;
@ -102,64 +198,17 @@ __bam_search(dbc, root_pgno, key, flags, stop, recnop, exactp)
* deleted items, and if we are locking pairs of pages. In addition, * deleted items, and if we are locking pairs of pages. In addition,
* if we're modifying record numbers, we have to lock the entire tree * if we're modifying record numbers, we have to lock the entire tree
* regardless. See btree.h for more details. * regardless. See btree.h for more details.
*
* If write-locking pages, we need to know whether or not to acquire a
* write lock on a page before getting it. This depends on how deep it
* is in tree, which we don't know until we acquire the root page. So,
* if we need to lock the root page we may have to upgrade it later,
* because we won't get the correct lock initially.
*
* Retrieve the root page.
*/ */
try_again:
pg = root_pgno == PGNO_INVALID ? cp->root : root_pgno;
stack = LF_ISSET(S_STACK) && F_ISSET(cp, C_RECNUM);
lock_mode = stack ? DB_LOCK_WRITE : DB_LOCK_READ;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
/* if (root_pgno == PGNO_INVALID)
* Decide if we need to save this page; if we do, write lock it. root_pgno = cp->root;
* We deliberately don't lock-couple on this call. If the tree if ((ret = __bam_get_root(dbc, root_pgno, slevel, flags, &stack)) != 0)
* is tiny, i.e., one page, and two threads are busily updating return (ret);
* the root page, we're almost guaranteed deadlocks galore, as lock_mode = cp->csp->lock_mode;
* each one gets a read lock and then blocks the other's attempt lock = cp->csp->lock;
* for a write lock. h = cp->csp->page;
*/
if (!stack && BT_STK_CLR(cp);
((LF_ISSET(S_PARENT) && (u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0)
return (ret);
if ((ret = __memp_fget(mpf, &pg, 0, &h)) != 0) {
/* Did not read it, so we can release the lock */
(void)__LPUT(dbc, lock);
return (ret);
}
if (!((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= h->level) ||
(LF_ISSET(S_WRITE) && h->level == LEAFLEVEL))) {
/* Someone else split the root, start over. */
ret = __memp_fput(mpf, h, 0);
if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0)
ret = t_ret;
if (ret != 0)
return (ret);
goto try_again;
}
stack = 1;
}
/* Choose a comparison function. */ /* Choose a comparison function. */
func = F_ISSET(dbc, DBC_OPD) ? func = F_ISSET(dbc, DBC_OPD) ?
@ -168,6 +217,23 @@ try_again:
for (;;) { for (;;) {
inp = P_INP(dbp, h); inp = P_INP(dbp, h);
adjust = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
if (LF_ISSET(S_MIN | S_MAX)) {
if (LF_ISSET(S_MIN) || NUM_ENT(h) == 0)
indx = 0;
else if (TYPE(h) == P_LBTREE)
indx = NUM_ENT(h) - 2;
else
indx = NUM_ENT(h) - 1;
if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) && LEVEL(h) == slevel)) {
if (LF_ISSET(S_NEXT))
goto get_next;
goto found;
}
goto next;
}
/* /*
* Do a binary search on the current page. If we're searching * Do a binary search on the current page. If we're searching
* a Btree leaf page, we have to walk the indices in groups of * a Btree leaf page, we have to walk the indices in groups of
@ -175,7 +241,6 @@ try_again:
* page, they're an index per page item. If we find an exact * page, they're an index per page item. If we find an exact
* match on a leaf page, we're done. * match on a leaf page, we're done.
*/ */
adjust = TYPE(h) == P_LBTREE ? P_INDX : O_INDX;
for (base = 0, for (base = 0,
lim = NUM_ENT(h) / (db_indx_t)adjust; lim != 0; lim >>= 1) { lim = NUM_ENT(h) / (db_indx_t)adjust; lim != 0; lim >>= 1) {
indx = base + ((lim >> 1) * adjust); indx = base + ((lim >> 1) * adjust);
@ -183,8 +248,13 @@ try_again:
__bam_cmp(dbp, key, h, indx, func, &cmp)) != 0) __bam_cmp(dbp, key, h, indx, func, &cmp)) != 0)
goto err; goto err;
if (cmp == 0) { if (cmp == 0) {
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP) if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) &&
LEVEL(h) == slevel)) {
if (LF_ISSET(S_NEXT))
goto get_next;
goto found; goto found;
}
goto next; goto next;
} }
if (cmp > 0) { if (cmp > 0) {
@ -197,10 +267,12 @@ try_again:
* No match found. Base is the smallest index greater than * No match found. Base is the smallest index greater than
* key and may be zero or a last + O_INDX index. * key and may be zero or a last + O_INDX index.
* *
* If it's a leaf page, return base as the "found" value. * If it's a leaf page or the stopping point,
* return base as the "found" value.
* Delete only deletes exact matches. * Delete only deletes exact matches.
*/ */
if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP) { if (LEVEL(h) == LEAFLEVEL ||
(!LF_ISSET(S_START) && LEVEL(h) == slevel)) {
*exactp = 0; *exactp = 0;
if (LF_ISSET(S_EXACT)) { if (LF_ISSET(S_EXACT)) {
@ -218,6 +290,43 @@ try_again:
ret = t_ret; ret = t_ret;
return (ret); return (ret);
} }
if (LF_ISSET(S_NEXT)) {
get_next: /*
* The caller could have asked for a NEXT
* at the root if the tree recently collapsed.
*/
if (PGNO(h) == root_pgno) {
ret = DB_NOTFOUND;
goto err;
}
/*
* Save the root of the subtree
* and drop the rest of the subtree
* and search down again starting at
* the next child.
*/
if ((ret = __LPUT(dbc, lock)) != 0)
goto err;
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
h = NULL;
LF_SET(S_MIN);
LF_CLR(S_NEXT);
indx = cp->sp->indx + 1;
if (indx == NUM_ENT(cp->sp->page)) {
ret = DB_NOTFOUND;
cp->csp++;
goto err;
}
h = cp->sp->page;
cp->sp->page = NULL;
lock = cp->sp->lock;
LOCK_INIT(cp->sp->lock);
if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
stack = 1;
goto next;
}
/* /*
* !!! * !!!
@ -227,6 +336,8 @@ try_again:
* to find an undeleted record. This is handled by the * to find an undeleted record. This is handled by the
* calling routine. * calling routine.
*/ */
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv, BT_STK_ENTER(dbp->dbenv,
cp, h, base, lock, lock_mode, ret); cp, h, base, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
@ -252,8 +363,12 @@ next: if (recnop != NULL)
pg = GET_BINTERNAL(dbp, h, indx)->pgno; pg = GET_BINTERNAL(dbp, h, indx)->pgno;
/* See if we are at the level to start stacking. */
if (LF_ISSET(S_START) && slevel == LEVEL(h))
stack = 1;
if (LF_ISSET(S_STK_ONLY)) { if (LF_ISSET(S_STK_ONLY)) {
if (stop == h->level) { if (slevel == LEVEL(h)) {
BT_STK_NUM(dbp->dbenv, cp, h, indx, ret); BT_STK_NUM(dbp->dbenv, cp, h, indx, ret);
if ((t_ret = if ((t_ret =
__LPUT(dbc, lock)) != 0 && ret == 0) __LPUT(dbc, lock)) != 0 && ret == 0)
@ -278,13 +393,24 @@ next: if (recnop != NULL)
} }
} else if (stack) { } else if (stack) {
/* Return if this is the lowest page wanted. */ /* Return if this is the lowest page wanted. */
if (LF_ISSET(S_PARENT) && stop == h->level) { if (LF_ISSET(S_PARENT) && slevel == LEVEL(h)) {
BT_STK_ENTER(dbp->dbenv, BT_STK_ENTER(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret); cp, h, indx, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
goto err; goto err;
return (0); return (0);
} }
if (LF_ISSET(S_DEL) && NUM_ENT(h) > 1) {
/*
* There was a page with a singleton pointer
* to a non-empty subtree.
*/
cp->csp--;
if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
stack = 0;
goto do_del;
}
BT_STK_PUSH(dbp->dbenv, BT_STK_PUSH(dbp->dbenv,
cp, h, indx, lock, lock_mode, ret); cp, h, indx, lock, lock_mode, ret);
if (ret != 0) if (ret != 0)
@ -302,16 +428,69 @@ next: if (recnop != NULL)
* unlock it. * unlock it.
*/ */
if ((LF_ISSET(S_PARENT) && if ((LF_ISSET(S_PARENT) &&
(u_int8_t)(stop + 1) >= (u_int8_t)(h->level - 1)) || (u_int8_t)(slevel + 1) >= (LEVEL(h) - 1)) ||
(h->level - 1) == LEAFLEVEL) (LEVEL(h) - 1) == LEAFLEVEL)
stack = 1; stack = 1;
if ((ret = __memp_fput(mpf, h, 0)) != 0) /*
goto err; * Returning a subtree. See if we have hit the start
h = NULL; * point if so save the parent and set stack.
* Otherwise free the parent and temporarily
* save this one.
* For S_DEL we need to find a page with 1 entry.
* For S_NEXT we want find the minimal subtree
* that contains the key and the next page.
* We save pages as long as we are at the right
* edge of the subtree. When we leave the right
* edge, then drop the subtree.
*/
if (!LF_ISSET(S_DEL | S_NEXT)) {
if ((ret = __memp_fput(mpf, h, 0)) != 0)
goto err;
goto lock_next;
}
lock_mode = stack && if ((LF_ISSET(S_DEL) && NUM_ENT(h) == 1)) {
LF_ISSET(S_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ; stack = 1;
LF_SET(S_WRITE);
/* Push the parent. */
cp->csp++;
/* Push this node. */
BT_STK_PUSH(dbp->dbenv, cp, h,
indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
LOCK_INIT(lock);
} else {
/*
* See if we want to save the tree so far.
* If we are looking for the next key,
* then we must save this node if we are
* at the end of the page. If not then
* discard anything we have saved so far.
* For delete only keep one node until
* we find a singleton.
*/
do_del: if (cp->csp->page != NULL) {
if (LF_ISSET(S_NEXT) &&
indx == NUM_ENT(h) - 1)
cp->csp++;
else if ((ret =
__bam_stkrel(dbc, STK_NOLOCK)) != 0)
goto err;
}
/* Save this node. */
BT_STK_ENTER(dbp->dbenv, cp,
h, indx, lock, lock_mode, ret);
if (ret != 0)
goto err;
LOCK_INIT(lock);
}
lock_next: h = NULL;
if (stack && LF_ISSET(S_WRITE))
lock_mode = DB_LOCK_WRITE;
if ((ret = __db_lget(dbc, if ((ret = __db_lget(dbc,
LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) { LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) {
/* /*
@ -320,6 +499,8 @@ next: if (recnop != NULL)
* descending the tree holding read-locks. * descending the tree holding read-locks.
*/ */
(void)__LPUT(dbc, lock); (void)__LPUT(dbc, lock);
if (LF_ISSET(S_DEL | S_NEXT))
cp->csp++;
goto err; goto err;
} }
} }
@ -340,12 +521,12 @@ found: *exactp = 1;
* all duplicate sets that are not on overflow pages exist on a * all duplicate sets that are not on overflow pages exist on a
* single leaf page. * single leaf page.
*/ */
if (TYPE(h) == P_LBTREE) { if (TYPE(h) == P_LBTREE && NUM_ENT(h) > P_INDX) {
if (LF_ISSET(S_DUPLAST)) if (LF_ISSET(S_DUPLAST))
while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) &&
inp[indx] == inp[indx + P_INDX]) inp[indx] == inp[indx + P_INDX])
indx += P_INDX; indx += P_INDX;
else else if (LF_ISSET(S_DUPFIRST))
while (indx > 0 && while (indx > 0 &&
inp[indx] == inp[indx - P_INDX]) inp[indx] == inp[indx - P_INDX])
indx -= P_INDX; indx -= P_INDX;
@ -406,8 +587,11 @@ found: *exactp = 1;
ret = t_ret; ret = t_ret;
if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0) if ((t_ret = __memp_fput(mpf, h, 0)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
} else } else {
if (LF_ISSET(S_DEL) && cp->csp == cp->sp)
cp->csp++;
BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret); BT_STK_ENTER(dbp->dbenv, cp, h, indx, lock, lock_mode, ret);
}
if (ret != 0) if (ret != 0)
goto err; goto err;
@ -471,6 +655,13 @@ __bam_stkrel(dbc, flags)
*/ */
epg->page = NULL; epg->page = NULL;
} }
/*
* We set this if we need to release our pins,
* but are not logically ready to have the pages
* visible.
*/
if (LF_ISSET(STK_PGONLY))
continue;
if (LF_ISSET(STK_NOLOCK)) { if (LF_ISSET(STK_NOLOCK)) {
if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0) if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0)
ret = t_ret; ret = t_ret;
@ -480,7 +671,8 @@ __bam_stkrel(dbc, flags)
} }
/* Clear the stack, all pages have been released. */ /* Clear the stack, all pages have been released. */
BT_STK_CLR(cp); if (!LF_ISSET(STK_PGONLY))
BT_STK_CLR(cp);
return (ret); return (ret);
} }

View file

@ -1,7 +1,7 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
*/ */
/* /*
@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* $Id: bt_split.c,v 11.66 2004/10/01 13:00:21 bostic Exp $ * $Id: bt_split.c,v 12.4 2005/06/16 20:20:22 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -56,7 +56,6 @@
static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *)); static int __bam_broot __P((DBC *, PAGE *, PAGE *, PAGE *));
static int __bam_page __P((DBC *, EPG *, EPG *)); static int __bam_page __P((DBC *, EPG *, EPG *));
static int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *, int));
static int __bam_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *)); static int __bam_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *));
static int __bam_root __P((DBC *, EPG *)); static int __bam_root __P((DBC *, EPG *));
static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *)); static int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *));
@ -338,7 +337,7 @@ __bam_page(dbc, pp, cp)
* page can't hold the new keys, and has to be split in turn, in which * page can't hold the new keys, and has to be split in turn, in which
* case we want to release all the locks we can. * case we want to release all the locks we can.
*/ */
if ((ret = __bam_pinsert(dbc, pp, lp, rp, 1)) != 0) if ((ret = __bam_pinsert(dbc, pp, lp, rp, BPI_SPACEONLY)) != 0)
goto err; goto err;
/* /*
@ -349,7 +348,7 @@ __bam_page(dbc, pp, cp)
* a page that's not in our direct ancestry. Consider a cursor walking * a page that's not in our direct ancestry. Consider a cursor walking
* backward through the leaf pages, that has our following page locked, * backward through the leaf pages, that has our following page locked,
* and is waiting on a lock for the page we're splitting. In that case * and is waiting on a lock for the page we're splitting. In that case
* we're going to deadlock here . It's probably OK, stepping backward * we're going to deadlock here. It's probably OK, stepping backward
* through the tree isn't a common operation. * through the tree isn't a common operation.
*/ */
if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID) { if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID) {
@ -685,13 +684,15 @@ __ram_root(dbc, rootp, lp, rp)
/* /*
* __bam_pinsert -- * __bam_pinsert --
* Insert a new key into a parent page, completing the split. * Insert a new key into a parent page, completing the split.
*
* PUBLIC: int __bam_pinsert __P((DBC *, EPG *, PAGE *, PAGE *, int));
*/ */
static int int
__bam_pinsert(dbc, parent, lchild, rchild, space_check) __bam_pinsert(dbc, parent, lchild, rchild, flags)
DBC *dbc; DBC *dbc;
EPG *parent; EPG *parent;
PAGE *lchild, *rchild; PAGE *lchild, *rchild;
int space_check; int flags;
{ {
BINTERNAL bi, *child_bi; BINTERNAL bi, *child_bi;
BKEYDATA *child_bk, *tmp_bk; BKEYDATA *child_bk, *tmp_bk;
@ -714,7 +715,7 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
/* If handling record numbers, count records split to the right page. */ /* If handling record numbers, count records split to the right page. */
nrecs = F_ISSET(cp, C_RECNUM) && nrecs = F_ISSET(cp, C_RECNUM) &&
!space_check ? __bam_total(dbp, rchild) : 0; !LF_ISSET(BPI_SPACEONLY) ? __bam_total(dbp, rchild) : 0;
/* /*
* Now we insert the new page's first key into the parent page, which * Now we insert the new page's first key into the parent page, which
@ -750,7 +751,7 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
if (P_FREESPACE(dbp, ppage) < nbytes) if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
/* Add a new record for the right page. */ /* Add a new record for the right page. */
@ -780,7 +781,11 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
child_bk = GET_BKEYDATA(dbp, rchild, 0); child_bk = GET_BKEYDATA(dbp, rchild, 0);
switch (B_TYPE(child_bk->type)) { switch (B_TYPE(child_bk->type)) {
case B_KEYDATA: case B_KEYDATA:
nbytes = BINTERNAL_PSIZE(child_bk->len);
nksize = child_bk->len;
/* /*
* Prefix compression:
* We set t->bt_prefix to NULL if we have a comparison * We set t->bt_prefix to NULL if we have a comparison
* callback but no prefix compression callback. But, * callback but no prefix compression callback. But,
* if we're splitting in an off-page duplicates tree, * if we're splitting in an off-page duplicates tree,
@ -792,6 +797,14 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
* as there's no way for an application to specify a * as there's no way for an application to specify a
* prefix compression callback that corresponds to its * prefix compression callback that corresponds to its
* comparison callback. * comparison callback.
*
* No prefix compression if we don't have a compression
* function, or the key we'd compress isn't a normal
* key (for example, it references an overflow page).
*
* Generate a parent page key for the right child page
* from a comparison of the last key on the left child
* page and the first key on the right child page.
*/ */
if (F_ISSET(dbc, DBC_OPD)) { if (F_ISSET(dbc, DBC_OPD)) {
if (dbp->dup_compare == __bam_defcmp) if (dbp->dup_compare == __bam_defcmp)
@ -800,13 +813,8 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
func = NULL; func = NULL;
} else } else
func = t->bt_prefix; func = t->bt_prefix;
nbytes = BINTERNAL_PSIZE(child_bk->len);
nksize = child_bk->len;
if (func == NULL) if (func == NULL)
goto noprefix; goto noprefix;
if (ppage->prev_pgno == PGNO_INVALID && off <= 1)
goto noprefix;
tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) - tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) -
(TYPE(lchild) == P_LDUP ? O_INDX : P_INDX)); (TYPE(lchild) == P_LDUP ? O_INDX : P_INDX));
if (B_TYPE(tmp_bk->type) != B_KEYDATA) if (B_TYPE(tmp_bk->type) != B_KEYDATA)
@ -821,11 +829,11 @@ __bam_pinsert(dbc, parent, lchild, rchild, space_check)
if ((n = BINTERNAL_PSIZE(nksize)) < nbytes) if ((n = BINTERNAL_PSIZE(nksize)) < nbytes)
nbytes = n; nbytes = n;
else else
noprefix: nksize = child_bk->len; nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes) noprefix: if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
@ -849,7 +857,7 @@ noprefix: nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes) if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
memset(&bi, 0, sizeof(bi)); memset(&bi, 0, sizeof(bi));
@ -883,7 +891,7 @@ noprefix: nksize = child_bk->len;
if (P_FREESPACE(dbp, ppage) < nbytes) if (P_FREESPACE(dbp, ppage) < nbytes)
return (DB_NEEDSPLIT); return (DB_NEEDSPLIT);
if (space_check) if (LF_ISSET(BPI_SPACEONLY))
return (0); return (0);
/* Add a new record for the right page. */ /* Add a new record for the right page. */
@ -904,13 +912,13 @@ noprefix: nksize = child_bk->len;
* If a Recno or Btree with record numbers AM page, or an off-page * If a Recno or Btree with record numbers AM page, or an off-page
* duplicates tree, adjust the parent page's left page record count. * duplicates tree, adjust the parent page's left page record count.
*/ */
if (F_ISSET(cp, C_RECNUM)) { if (F_ISSET(cp, C_RECNUM) && !LF_ISSET(BPI_NORECNUM)) {
/* Log the change. */ /* Log the change. */
if (DBC_LOGGING(dbc)) { if (DBC_LOGGING(dbc)) {
if ((ret = __bam_cadjust_log(dbp, dbc->txn, if ((ret = __bam_cadjust_log(dbp, dbc->txn,
&LSN(ppage), 0, PGNO(ppage), &LSN(ppage), 0, PGNO(ppage), &LSN(ppage),
&LSN(ppage), parent->indx, -(int32_t)nrecs, 0)) != 0) parent->indx, -(int32_t)nrecs, 0)) != 0)
return (ret); return (ret);
} else } else
LSN_NOT_LOGGED(LSN(ppage)); LSN_NOT_LOGGED(LSN(ppage));

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_stat.c,v 11.78 2004/09/22 03:31:26 bostic Exp $ * $Id: bt_stat.c,v 12.3 2005/06/16 20:20:23 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -155,7 +155,6 @@ meta_only:
/* Get metadata page statistics. */ /* Get metadata page statistics. */
sp->bt_metaflags = meta->dbmeta.flags; sp->bt_metaflags = meta->dbmeta.flags;
sp->bt_maxkey = meta->maxkey;
sp->bt_minkey = meta->minkey; sp->bt_minkey = meta->minkey;
sp->bt_re_len = meta->re_len; sp->bt_re_len = meta->re_len;
sp->bt_re_pad = meta->re_pad; sp->bt_re_pad = meta->re_pad;
@ -246,16 +245,12 @@ __bam_stat_print(dbc, flags)
} }
__db_msg(dbenv, "%s\tByte order", s); __db_msg(dbenv, "%s\tByte order", s);
__db_prflags(dbenv, NULL, sp->bt_metaflags, fn, NULL, "\tFlags"); __db_prflags(dbenv, NULL, sp->bt_metaflags, fn, NULL, "\tFlags");
if (dbp->type == DB_BTREE) { if (dbp->type == DB_BTREE)
#ifdef NOT_IMPLEMENTED
__db_dl(dbenv, "Maximum keys per-page", (u_long)sp->bt_maxkey);
#endif
__db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey); __db_dl(dbenv, "Minimum keys per-page", (u_long)sp->bt_minkey);
}
if (dbp->type == DB_RECNO) { if (dbp->type == DB_RECNO) {
__db_dl(dbenv, __db_dl(dbenv,
"Fixed-length record size", (u_long)sp->bt_re_len); "Fixed-length record size", (u_long)sp->bt_re_len);
__db_dl(dbenv, __db_msg(dbenv,
"%#x\tFixed-length record pad", (u_int)sp->bt_re_pad); "%#x\tFixed-length record pad", (u_int)sp->bt_re_pad);
} }
__db_dl(dbenv, __db_dl(dbenv,

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_upgrade.c,v 11.30 2004/01/28 03:35:49 bostic Exp $ * $Id: bt_upgrade.c,v 12.1 2005/06/16 20:20:23 bostic Exp $
*/ */
#include "db_config.h" #include "db_config.h"

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: bt_verify.c,v 1.97 2004/10/11 18:47:46 bostic Exp $ * $Id: bt_verify.c,v 12.13 2005/11/11 20:27:49 ubell Exp $
*/ */
#include "db_config.h" #include "db_config.h"
@ -89,10 +89,8 @@ __bam_vrfy_meta(dbp, vdp, meta, pgno, flags)
} else } else
pip->bt_minkey = meta->minkey; pip->bt_minkey = meta->minkey;
/* bt_maxkey: unsupported so no constraints. */
pip->bt_maxkey = meta->maxkey;
/* re_len: no constraints on this (may be zero or huge--we make rope) */ /* re_len: no constraints on this (may be zero or huge--we make rope) */
pip->re_pad = meta->re_pad;
pip->re_len = meta->re_len; pip->re_len = meta->re_len;
/* /*
@ -1618,8 +1616,17 @@ bad_prev: isbad = 1;
if (relenp) if (relenp)
*relenp = relen; *relenp = relen;
} }
if (LF_ISSET(ST_RECNUM)) if (LF_ISSET(ST_RECNUM)) {
if (child->nrecs != child_nrecs) {
isbad = 1;
EPRINT((dbenv,
"Page %lu: record count incorrect: actual %lu, in record %lu",
(u_long)child->pgno,
(u_long)child_nrecs,
(u_long)child->nrecs));
}
nrecs += child_nrecs; nrecs += child_nrecs;
}
if (isbad == 0 && level != child_level + 1) { if (isbad == 0 && level != child_level + 1) {
isbad = 1; isbad = 1;
EPRINT((dbenv, EPRINT((dbenv,
@ -2037,38 +2044,36 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
DBT *key; DBT *key;
u_int32_t flags; u_int32_t flags;
{ {
DBT dbt, unkdbt;
DB_ENV *dbenv;
BKEYDATA *bk; BKEYDATA *bk;
BOVERFLOW *bo; BOVERFLOW *bo;
DBT dbt, unknown_key, unknown_data;
DB_ENV *dbenv;
VRFY_ITEM *pgmap; VRFY_ITEM *pgmap;
db_indx_t i, beg, end, *inp; db_indx_t i, last, beg, end, *inp;
u_int32_t himark; u_int32_t himark;
void *ovflbuf; void *ovflbuf;
int t_ret, ret, err_ret; int ret, t_ret, t2_ret;
dbenv = dbp->dbenv; dbenv = dbp->dbenv;
/* Shut up lint. */
COMPQUIET(end, 0);
ovflbuf = pgmap = NULL; ovflbuf = pgmap = NULL;
err_ret = ret = 0;
inp = P_INP(dbp, h); inp = P_INP(dbp, h);
memset(&dbt, 0, sizeof(DBT)); memset(&dbt, 0, sizeof(DBT));
dbt.flags = DB_DBT_REALLOC; dbt.flags = DB_DBT_REALLOC;
memset(&unkdbt, 0, sizeof(DBT)); memset(&unknown_key, 0, sizeof(DBT));
unkdbt.size = (u_int32_t)(strlen("UNKNOWN") + 1); unknown_key.size = (u_int32_t)strlen("UNKNOWN_KEY");
unkdbt.data = "UNKNOWN"; unknown_key.data = "UNKNOWN_KEY";
memset(&unknown_data, 0, sizeof(DBT));
unknown_data.size = (u_int32_t)strlen("UNKNOWN_DATA");
unknown_data.data = "UNKNOWN_DATA";
/* /*
* Allocate a buffer for overflow items. Start at one page; * Allocate a buffer for overflow items. Start at one page;
* __db_safe_goff will realloc as needed. * __db_safe_goff will realloc as needed.
*/ */
if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0) if ((ret = __os_malloc(dbenv, dbp->pgsize, &ovflbuf)) != 0)
return (ret); goto err;
if (LF_ISSET(DB_AGGRESSIVE) && (ret = if (LF_ISSET(DB_AGGRESSIVE) && (ret =
__os_calloc(dbenv, dbp->pgsize, sizeof(pgmap[0]), &pgmap)) != 0) __os_calloc(dbenv, dbp->pgsize, sizeof(pgmap[0]), &pgmap)) != 0)
@ -2077,161 +2082,185 @@ __bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags)
/* /*
* Loop through the inp array, spitting out key/data pairs. * Loop through the inp array, spitting out key/data pairs.
* *
* If we're salvaging normally, loop from 0 through NUM_ENT(h). * If we're salvaging normally, loop from 0 through NUM_ENT(h). If
* If we're being aggressive, loop until we hit the end of the page-- * we're being aggressive, loop until we hit the end of the page --
* NUM_ENT() may be bogus. * NUM_ENT() may be bogus.
*/ */
himark = dbp->pgsize; himark = dbp->pgsize;
for (i = 0;; i += O_INDX) { for (i = 0, last = UINT16_MAX;; i += O_INDX) {
/* If we're not aggressive, break when we hit NUM_ENT(h). */ /* If we're not aggressive, break when we hit NUM_ENT(h). */
if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h)) if (!LF_ISSET(DB_AGGRESSIVE) && i >= NUM_ENT(h))
break; break;
/* Verify the current item. */ /* Verify the current item. */
ret = __db_vrfy_inpitem(dbp, t_ret =
h, pgno, i, 1, flags, &himark, NULL); __db_vrfy_inpitem(dbp, h, pgno, i, 1, flags, &himark, NULL);
/* If this returned a fatality, it's time to break. */
if (ret == DB_VERIFY_FATAL) { if (t_ret != 0) {
/* /*
* Don't return DB_VERIFY_FATAL; it's private * If this is a btree leaf and we've printed out a key
* and means only that we can't go on with this * but not its associated data item, fix this imbalance
* page, not with the whole database. It's * by printing an "UNKNOWN_DATA".
* not even an error if we've run into it
* after NUM_ENT(h).
*/ */
ret = (i < NUM_ENT(h)) ? DB_VERIFY_BAD : 0; if (pgtype == P_LBTREE && i % P_INDX == 1 &&
break; last == i - 1 && (t2_ret = __db_vrfy_prdbt(
&unknown_data,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t2_ret;
goto err;
}
/*
* Don't return DB_VERIFY_FATAL; it's private and means
* only that we can't go on with this page, not with
* the whole database. It's not even an error if we've
* run into it after NUM_ENT(h).
*/
if (t_ret == DB_VERIFY_FATAL) {
if (i < NUM_ENT(h) && ret == 0)
ret = DB_VERIFY_BAD;
break;
}
continue;
} }
/* /*
* If this returned 0, it's safe to print or (carefully) * If this returned 0, it's safe to print or (carefully)
* try to fetch. * try to fetch.
*
* We only print deleted items if DB_AGGRESSIVE is set.
*/ */
if (ret == 0) { bk = GET_BKEYDATA(dbp, h, i);
/* if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
* We only want to print deleted items if continue;
* DB_AGGRESSIVE is set.
*/
bk = GET_BKEYDATA(dbp, h, i);
if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type))
continue;
/* /*
* We're going to go try to print the next item. If * If this is a btree leaf and we're about to print out a data
* key is non-NULL, we're a dup page, so we've got to * item for which we didn't print out a key, fix this imbalance
* print the key first, unless SA_SKIPFIRSTKEY is set * by printing an "UNKNOWN_KEY".
* and we're on the first entry. */
*/ if (pgtype == P_LBTREE && i % P_INDX == 1 &&
if (key != NULL && last != i - 1 && (t_ret = __db_vrfy_prdbt(
(i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY))) &unknown_key, 0, " ", handle, callback, 0, vdp)) != 0) {
if ((ret = __db_vrfy_prdbt(key, if (ret == 0)
0, " ", handle, callback, 0, vdp)) != 0) ret = t_ret;
err_ret = ret; goto err;
}
last = i;
beg = inp[i]; /*
switch (B_TYPE(bk->type)) { * We're going to go try to print the next item. If key is
case B_DUPLICATE: * non-NULL, we're a dup page, so we've got to print the key
end = beg + BOVERFLOW_SIZE - 1; * first, unless SA_SKIPFIRSTKEY is set and we're on the first
/* * entry.
* If we're not on a normal btree leaf page, */
* there shouldn't be off-page if (key != NULL && (i != 0 || !LF_ISSET(SA_SKIPFIRSTKEY)))
* dup sets. Something's confused; just if ((t_ret = __db_vrfy_prdbt(key,
* drop it, and the code to pick up unlinked 0, " ", handle, callback, 0, vdp)) != 0) {
* offpage dup sets will print it out if (ret == 0)
* with key "UNKNOWN" later. ret = t_ret;
*/ goto err;
if (pgtype != P_LBTREE)
break;
bo = (BOVERFLOW *)bk;
/*
* If the page number is unreasonable, or
* if this is supposed to be a key item,
* just spit out "UNKNOWN"--the best we
* can do is run into the data items in the
* unlinked offpage dup pass.
*/
if (!IS_VALID_PGNO(bo->pgno) ||
(i % P_INDX == 0)) {
/* Not much to do on failure. */
if ((ret =
__db_vrfy_prdbt(&unkdbt, 0, " ",
handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
}
if ((ret = __db_salvage_duptree(dbp,
vdp, bo->pgno, &dbt, handle, callback,
flags | SA_SKIPFIRSTKEY)) != 0)
err_ret = ret;
break;
case B_KEYDATA:
end = (db_indx_t)DB_ALIGN(
beg + bk->len, sizeof(u_int32_t)) - 1;
dbt.data = bk->data;
dbt.size = bk->len;
if ((ret = __db_vrfy_prdbt(&dbt,
0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
case B_OVERFLOW:
end = beg + BOVERFLOW_SIZE - 1;
bo = (BOVERFLOW *)bk;
if ((ret = __db_safe_goff(dbp, vdp,
bo->pgno, &dbt, &ovflbuf, flags)) != 0) {
err_ret = ret;
/* We care about err_ret more. */
(void)__db_vrfy_prdbt(&unkdbt, 0, " ",
handle, callback, 0, vdp);
break;
}
if ((ret = __db_vrfy_prdbt(&dbt,
0, " ", handle, callback, 0, vdp)) != 0)
err_ret = ret;
break;
default:
/*
* We should never get here; __db_vrfy_inpitem
* should not be returning 0 if bk->type
* is unrecognizable.
*/
DB_ASSERT(0);
return (EINVAL);
} }
beg = inp[i];
switch (B_TYPE(bk->type)) {
case B_DUPLICATE:
end = beg + BOVERFLOW_SIZE - 1;
/* /*
* If we're being aggressive, mark the beginning * If we're not on a normal btree leaf page, there
* and end of the item; we'll come back and print * shouldn't be off-page dup sets. Something's
* whatever "junk" is in the gaps in case we had * confused; just drop it, and the code to pick up
* any bogus inp elements and thereby missed stuff. * unlinked offpage dup sets will print it out
* with key "UNKNOWN" later.
*/ */
if (LF_ISSET(DB_AGGRESSIVE)) { if (pgtype != P_LBTREE)
pgmap[beg] = VRFY_ITEM_BEGIN; break;
pgmap[end] = VRFY_ITEM_END;
bo = (BOVERFLOW *)bk;
/*
* If the page number is unreasonable, or if this is
* supposed to be a key item, output "UNKNOWN_KEY" --
* the best we can do is run into the data items in
* the unlinked offpage dup pass.
*/
if (!IS_VALID_PGNO(bo->pgno) || (i % P_INDX == 0)) {
/* Not much to do on failure. */
if ((t_ret = __db_vrfy_prdbt(&unknown_key,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t_ret;
goto err;
}
break;
} }
/* Don't stop on error. */
if ((t_ret = __db_salvage_duptree(dbp,
vdp, bo->pgno, &dbt, handle, callback,
flags | SA_SKIPFIRSTKEY)) != 0 && ret == 0)
ret = t_ret;
break;
case B_KEYDATA:
end = (db_indx_t)DB_ALIGN(
beg + bk->len, sizeof(u_int32_t)) - 1;
dbt.data = bk->data;
dbt.size = bk->len;
if ((t_ret = __db_vrfy_prdbt(&dbt,
0, " ", handle, callback, 0, vdp)) != 0) {
if (ret == 0)
ret = t_ret;
goto err;
}
break;
case B_OVERFLOW:
end = beg + BOVERFLOW_SIZE - 1;
bo = (BOVERFLOW *)bk;
/* Don't stop on error. */
if ((t_ret = __db_safe_goff(dbp, vdp,
bo->pgno, &dbt, &ovflbuf, flags)) != 0 && ret == 0)
ret = t_ret;
if ((t_ret = __db_vrfy_prdbt(
t_ret == 0 ? &dbt : &unknown_key,
0, " ", handle, callback, 0, vdp)) != 0 && ret == 0)
ret = t_ret;
break;
default:
/*
* We should never get here; __db_vrfy_inpitem should
* not be returning 0 if bk->type is unrecognizable.
*/
DB_ASSERT(0);
if (ret == 0)
ret = EINVAL;
goto err;
}
/*
* If we're being aggressive, mark the beginning and end of
* the item; we'll come back and print whatever "junk" is in
* the gaps in case we had any bogus inp elements and thereby
* missed stuff.
*/
if (LF_ISSET(DB_AGGRESSIVE)) {
pgmap[beg] = VRFY_ITEM_BEGIN;
pgmap[end] = VRFY_ITEM_END;
} }
} }
/*
* If i is odd and this is a btree leaf, we've printed out a key but not
* a datum; fix this imbalance by printing an "UNKNOWN".
*/
if (pgtype == P_LBTREE && (i % P_INDX == 1) && ((ret =
__db_vrfy_prdbt(&unkdbt, 0, " ", handle, callback, 0, vdp)) != 0))
err_ret = ret;
err: if (pgmap != NULL) err: if (pgmap != NULL)
__os_free(dbenv, pgmap); __os_free(dbenv, pgmap);
__os_free(dbenv, ovflbuf); if (ovflbuf != NULL)
__os_free(dbenv, ovflbuf);
/* Mark this page as done. */ /* Mark this page as done. */
if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0) if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0)
return (t_ret); ret = t_ret;
return ((err_ret != 0) ? err_ret : ret); return (ret);
} }
/* /*

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1996-2004 * Copyright (c) 1996-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: btree.src,v 10.42 2004/06/17 17:35:12 bostic Exp $ * $Id: btree.src,v 12.3 2005/08/08 03:37:05 ubell Exp $
*/ */
PREFIX __bam PREFIX __bam
@ -210,10 +210,10 @@ END
BEGIN relink 147 BEGIN relink 147
/* Fileid of db affected. */ /* Fileid of db affected. */
DB fileid int32_t ld DB fileid int32_t ld
/* The page being changed. */ /* The page being removed. */
ARG pgno db_pgno_t lu ARG pgno db_pgno_t lu
/* The page's original lsn. */ /* The new page number, if any. */
POINTER lsn DB_LSN * lu ARG new_pgno db_pgno_t lu
/* The previous page. */ /* The previous page. */
ARG prev db_pgno_t lu ARG prev db_pgno_t lu
/* The previous page's original lsn. */ /* The previous page's original lsn. */
@ -223,3 +223,30 @@ ARG next db_pgno_t lu
/* The previous page's original lsn. */ /* The previous page's original lsn. */
POINTER lsn_next DB_LSN * lu POINTER lsn_next DB_LSN * lu
END END
/*
* BTREE-merge -- Handles merging of pages during a compaction.
*/
BEGIN merge 148
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG npgno db_pgno_t lu
POINTER nlsn DB_LSN * lu
DBT hdr DBT s
DBT data DBT s
DBT ind DBT s
END
/*
* BTREE-pgno -- Handles replacing a page number in the record
* refernece on pgno by indx.
*/
BEGIN pgno 149
DB fileid int32_t ld
ARG pgno db_pgno_t lu
POINTER lsn DB_LSN * lu
ARG indx u_int32_t lu
ARG opgno db_pgno_t lu
ARG npgno db_pgno_t lu
END

View file

@ -1,29 +0,0 @@
Document file - DO NOT EDIT
<BEGIN> CORE_INFO_TYPE
Workspace
<END>
<BEGIN> CORE_INFO_VERSION
2.0
<END>
<BEGIN> projectList
$(PRJ_DIR)/BerkeleyDB.wpj \
$(PRJ_DIR)/db_archive/db_archive.wpj \
$(PRJ_DIR)/db_checkpoint/db_checkpoint.wpj \
$(PRJ_DIR)/db_deadlock/db_deadlock.wpj \
$(PRJ_DIR)/db_dump/db_dump.wpj \
$(PRJ_DIR)/db_load/db_load.wpj \
$(PRJ_DIR)/db_printlog/db_printlog.wpj \
$(PRJ_DIR)/db_recover/db_recover.wpj \
$(PRJ_DIR)/db_stat/db_stat.wpj \
$(PRJ_DIR)/db_upgrade/db_upgrade.wpj \
$(PRJ_DIR)/db_verify/db_verify.wpj \
$(PRJ_DIR)/dbdemo/dbdemo.wpj
<END>
<BEGIN> userComments
<END>

View file

@ -1,251 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2004
* Sleepycat Software. All rights reserved.
*
* $Id: db_deadlock.c,v 11.45 2004/03/24 15:13:12 bostic Exp $
*/
#include "db_config.h"
#ifndef lint
static const char copyright[] =
"Copyright (c) 1996-2004\nSleepycat Software Inc. All rights reserved.\n";
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#include "db_int.h"
int db_deadlock_main __P((int, char *[]));
int db_deadlock_usage __P((void));
int db_deadlock_version_check __P((const char *));
int
db_deadlock(args)
char *args;
{
int argc;
char **argv;
__db_util_arg("db_deadlock", args, &argc, &argv);
return (db_deadlock_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS);
}
#include <stdio.h>
#define ERROR_RETURN ERROR
int
db_deadlock_main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind, __db_getopt_reset;
const char *progname = "db_deadlock";
DB_ENV *dbenv;
u_int32_t atype;
time_t now;
u_long secs, usecs;
int ch, exitval, ret, verbose;
char *home, *logfile, *str;
if ((ret = db_deadlock_version_check(progname)) != 0)
return (ret);
dbenv = NULL;
atype = DB_LOCK_DEFAULT;
home = logfile = NULL;
secs = usecs = 0;
exitval = verbose = 0;
__db_getopt_reset = 1;
while ((ch = getopt(argc, argv, "a:h:L:t:Vvw")) != EOF)
switch (ch) {
case 'a':
switch (optarg[0]) {
case 'e':
atype = DB_LOCK_EXPIRE;
break;
case 'm':
atype = DB_LOCK_MAXLOCKS;
break;
case 'n':
atype = DB_LOCK_MINLOCKS;
break;
case 'o':
atype = DB_LOCK_OLDEST;
break;
case 'W':
atype = DB_LOCK_MAXWRITE;
break;
case 'w':
atype = DB_LOCK_MINWRITE;
break;
case 'y':
atype = DB_LOCK_YOUNGEST;
break;
default:
return (db_deadlock_usage());
/* NOTREACHED */
}
if (optarg[1] != '\0')
return (db_deadlock_usage());
break;
case 'h':
home = optarg;
break;
case 'L':
logfile = optarg;
break;
case 't':
if ((str = strchr(optarg, '.')) != NULL) {
*str++ = '\0';
if (*str != '\0' && __db_getulong(
NULL, progname, str, 0, LONG_MAX, &usecs))
return (EXIT_FAILURE);
}
if (*optarg != '\0' && __db_getulong(
NULL, progname, optarg, 0, LONG_MAX, &secs))
return (EXIT_FAILURE);
if (secs == 0 && usecs == 0)
return (db_deadlock_usage());
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
return (EXIT_SUCCESS);
case 'v':
verbose = 1;
break;
case 'w': /* Undocumented. */
/* Detect every 100ms (100000 us) when polling. */
secs = 0;
usecs = 100000;
break;
case '?':
default:
return (db_deadlock_usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (db_deadlock_usage());
/* Handle possible interruptions. */
__db_util_siginit();
/* Log our process ID. */
if (logfile != NULL && __db_util_logset(progname, logfile))
goto shutdown;
/*
* Create an environment object and initialize it for error
* reporting.
*/
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
goto shutdown;
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
if (verbose) {
(void)dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1);
(void)dbenv->set_verbose(dbenv, DB_VERB_WAITSFOR, 1);
}
/* An environment is required. */
if ((ret =
dbenv->open(dbenv, home, DB_INIT_LOCK | DB_USE_ENVIRON, 0)) != 0) {
dbenv->err(dbenv, ret, "open");
goto shutdown;
}
while (!__db_util_interrupted()) {
if (verbose) {
(void)time(&now);
dbenv->errx(dbenv, "running at %.24s", ctime(&now));
}
if ((ret = dbenv->lock_detect(dbenv, 0, atype, NULL)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->lock_detect");
goto shutdown;
}
/* Make a pass every "secs" secs and "usecs" usecs. */
if (secs == 0 && usecs == 0)
break;
__os_sleep(dbenv, secs, usecs);
}
if (0) {
shutdown: exitval = 1;
}
/* Clean up the logfile. */
if (logfile != NULL)
(void)remove(logfile);
/* Clean up the environment. */
if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
fprintf(stderr,
"%s: dbenv->close: %s\n", progname, db_strerror(ret));
}
/* Resend any caught signal. */
__db_util_sigresend();
return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
int
db_deadlock_usage()
{
(void)fprintf(stderr, "%s\n\t%s\n",
"usage: db_deadlock [-Vv]",
"[-a e | m | n | o | W | w | y] [-h home] [-L file] [-t sec.usec]");
return (EXIT_FAILURE);
}
int
db_deadlock_version_check(progname)
const char *progname;
{
int v_major, v_minor, v_patch;
/* Make sure we're loaded with the right version of the DB library. */
(void)db_version(&v_major, &v_minor, &v_patch);
if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) {
fprintf(stderr,
"%s: version %d.%d doesn't match library version %d.%d\n",
progname, DB_VERSION_MAJOR, DB_VERSION_MINOR,
v_major, v_minor);
return (EXIT_FAILURE);
}
return (0);
}

View file

@ -1,39 +0,0 @@
This README describes the steps needed to run a demo example of BerkeleyDB.
1. Read the pages in the Reference Guide that describe building
BerkeleyDB on VxWorks:
$(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/intro.html
$(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/notes.html
$(WIND_BASE)/target/src/BerkeleyDB/docs/ref/build_vxworks/faq.html
2. Launch Tornado 2.0 and open up the BerkeleyDB project.
3. Add the demo project to that workspace:
$(WIND_BASE)/target/src/BerkeleyDB/build_vxworks/demo/dbdemo.wpj
4. Build BerkeleyDB as described in the Reference Guide.
5. Build the dbdemo project.
6. Download BerkeleyDB onto the target.
7. Download the dbdemo project onto the target.
8. Open a windsh to the target and run the demo:
-> dbdemo "<pathname>/<dbname>"
Where pathname is a pathname string pointing to a directory that the
demo can create a database in. That directory should already exist.
The dbname is the name for the database. For example:
-> dbdemo "/tmp/demo.db"
9. The demo program will ask for input. You can type in any string.
The program will add an entry to the database with that string as
the key and the reverse of that string as the data item for that key.
It will continue asking for input until you hit ^D or enter "quit".
Upon doing so, the demo program will display all the keys you have
entered as input and their data items.

View file

@ -21,12 +21,15 @@ Package=<4>
Project_Dep_Name db_deadlock Project_Dep_Name db_deadlock
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_DLL Project_Dep_Name db_dll
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_dump Project_Dep_Name db_dump
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_hotbackup
End Project Dependency
Begin Project Dependency
Project_Dep_Name db_load Project_Dep_Name db_load
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
@ -45,7 +48,7 @@ Package=<4>
Project_Dep_Name db_verify Project_Dep_Name db_verify
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_Static Project_Dep_Name db_static
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name ex_access Project_Dep_Name ex_access
@ -63,9 +66,18 @@ Package=<4>
Project_Dep_Name ex_mpool Project_Dep_Name ex_mpool
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name ex_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_tpcb Project_Dep_Name ex_tpcb
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name example_database_load
End Project Dependency
Begin Project Dependency
Project_Dep_Name example_database_read
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_access Project_Dep_Name excxx_access
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
@ -81,10 +93,31 @@ Package=<4>
Project_Dep_Name excxx_mpool Project_Dep_Name excxx_mpool
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name excxx_sequence
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_tpcb Project_Dep_Name excxx_tpcb
End Project Dependency End Project Dependency
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name excxx_example_database_load
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_example_database_read
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_repquote
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_txnguide
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_txnguide_inmem
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_txnguide
End Project Dependency
Begin Project Dependency
Project_Dep_Name excxx_txnguide_inmem
End Project Dependency End Project Dependency
}}} }}}
@ -99,7 +132,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -114,7 +147,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -129,7 +162,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_DLL Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -156,7 +189,22 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "db_hotbackup"=.\db_hotbackup.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -168,29 +216,11 @@ Package=<5>
{{{ {{{
}}} }}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name DB_DLL
End Project Dependency
}}}
###############################################################################
Project: "db_lib"=.\db_lib.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_dll Project_Dep_Name db_dll
End Project Dependency End Project Dependency
Begin Project Dependency
Project_Dep_Name db_static
End Project Dependency
}}} }}}
############################################################################### ###############################################################################
@ -204,7 +234,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -219,7 +249,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -234,12 +264,24 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
############################################################################### ###############################################################################
Project: "db_small"=.\db_small.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "db_stat"=.\db_stat.dsp - Package Owner=<4> Project: "db_stat"=.\db_stat.dsp - Package Owner=<4>
Package=<5> Package=<5>
@ -249,7 +291,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -276,7 +318,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name DB_DLL Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -309,7 +351,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -324,7 +366,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -339,7 +381,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -354,7 +396,58 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_csvcode"=.\ex_csvcode.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_csvload"=.\ex_csvload.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_csvcode
End Project Dependency
}}}
###############################################################################
Project: "ex_csvquery"=.\ex_csvquery.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
Begin Project Dependency
Project_Dep_Name ex_csvcode
End Project Dependency End Project Dependency
}}} }}}
@ -369,7 +462,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -384,7 +477,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -399,7 +492,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -414,7 +507,22 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_sequence"=.\ex_sequence.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -429,7 +537,67 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_txnguide"=.\ex_txnguide.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "ex_txnguide_inmem"=.\ex_txnguide_inmem.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "example_database_load"=.\example_database_load.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "example_database_read"=.\example_database_read.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -444,7 +612,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -459,7 +627,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -474,7 +642,37 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_example_database_load"=.\excxx_example_database_load.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_example_database_read"=.\excxx_example_database_read.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -489,7 +687,7 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -504,7 +702,22 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_sequence"=.\excxx_sequence.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}
@ -519,7 +732,37 @@ Package=<5>
Package=<4> Package=<4>
{{{ {{{
Begin Project Dependency Begin Project Dependency
Project_Dep_Name db_lib Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_txnguide"=.\excxx_txnguide.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency
}}}
###############################################################################
Project: "excxx_txnguide_inmem"=.\excxx_txnguide_inmem.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name db_dll
End Project Dependency End Project Dependency
}}} }}}

View file

@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) Console Application" 0x0103 # TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=@project_name@ - Win32 Debug Static CFG=@project_name@ - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run !MESSAGE use the Export Makefile command and run
!MESSAGE !MESSAGE
@ -13,14 +13,18 @@ CFG=@project_name@ - Win32 Debug Static
!MESSAGE You can specify a configuration when running NMAKE !MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE !MESSAGE
!MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug Static" !MESSAGE NMAKE /f "@project_name@.mak" CFG="@project_name@ - Win32 Debug"
!MESSAGE !MESSAGE
!MESSAGE Possible choices for configuration are: !MESSAGE Possible choices for configuration are:
!MESSAGE !MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Release Static" (based on "Win32 (x86) Console Application") !MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win32 Debug Static" (based on "Win32 (x86) Console Application") !MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Console Application")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Console Application")
!MESSAGE !MESSAGE
# Begin Project # Begin Project
@ -34,99 +38,207 @@ RSC=rc.exe
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "@bin_rel_dest@"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release" # PROP Output_Dir "@bin_rel_dest@"
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" # ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug" !ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "@bin_debug_dest@"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug" # PROP Output_Dir "@bin_debug_dest@"
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no # ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Release Static" !ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_ASCII"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "@bin_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0 # PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release_static" # PROP Output_Dir "@bin_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_static" # PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib /nologo /subsystem:console /machine:I386 # ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt"
# ADD LINK32 Release_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@s.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_ASCII"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug Static" !ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "@bin_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0 # PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug_static" # PROP Output_Dir "@bin_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_static" # PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MTd /W3 /GX /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no # ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:AMD64 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 Debug_static/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@sd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /pdb:none /debug /machine:I386 /fixed:no # ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:AMD64 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_AMD64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:AMD64 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:AMD64 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_AMD64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@bin_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@bin_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.lib @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /debug /machine:IA64 /nodefaultlib:"libcmtd" /fixed:no /libpath:"@lib_debug_dest@_IA64"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@bin_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@bin_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /I "." /I ".." /D "WIN32" /D "NDEBUG" /D "_CONSOLE" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt"
# ADD LINK32 libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.lib @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:console /machine:IA64 /nodefaultlib:"libcmt" /libpath:"@lib_rel_dest@_IA64"
@POST_BUILD@
!ENDIF !ENDIF
@ -134,8 +246,12 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release" # Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug" # Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 Release Static" # Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 Debug Static" # Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@ @SOURCE_FILES@
# Begin Source File # Begin Source File

View file

@ -1,10 +1,10 @@
/*- /*-
* See the file LICENSE for redistribution information. * See the file LICENSE for redistribution information.
* *
* Copyright (c) 1999-2004 * Copyright (c) 1999-2005
* Sleepycat Software. All rights reserved. * Sleepycat Software. All rights reserved.
* *
* $Id: dbkill.cpp,v 11.9 2004/01/28 03:35:52 bostic Exp $ * $Id: dbkill.cpp,v 12.1 2005/06/16 20:20:43 bostic Exp $
*/ */
/* /*
* Kill - * Kill -

View file

@ -19,6 +19,12 @@ CFG=@project_name@ - Win32 Debug
!MESSAGE !MESSAGE
!MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "@project_name@ - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "@project_name@ - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 ASCII Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win32 ASCII Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Debug AMD64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Release AMD64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Debug IA64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "@project_name@ - Win64 Release IA64" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE !MESSAGE
# Begin Project # Begin Project
@ -33,17 +39,17 @@ RSC=rc.exe
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0 # PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release" # PROP BASE Output_Dir "@lib_rel_dest@"
# PROP BASE Intermediate_Dir "Release" # PROP BASE Intermediate_Dir "Release/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 0 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 0 # PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release" # PROP Output_Dir "@lib_rel_dest@"
# PROP Intermediate_Dir "Release" # PROP Intermediate_Dir "Release/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c # ADD BASE CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
@ -52,24 +58,25 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 # ADD BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"Release/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" # ADD LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug" !ELSEIF "$(CFG)" == "@project_name@ - Win32 Debug"
# PROP BASE Use_MFC 0 # PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1 # PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug" # PROP BASE Output_Dir "@lib_debug_dest@"
# PROP BASE Intermediate_Dir "Debug" # PROP BASE Intermediate_Dir "Debug/@project_name@"
# PROP BASE Target_Dir "" # PROP BASE Target_Dir ""
# PROP Use_MFC 2 # PROP Use_MFC 0
# PROP Use_Debug_Libraries 1 # PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug" # PROP Output_Dir "@lib_debug_dest@"
# PROP Intermediate_Dir "Debug" # PROP Intermediate_Dir "Debug/@project_name@"
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c # ADD BASE CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX"config.h" /FD /c # ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# SUBTRACT CPP /Fr # SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
@ -79,8 +86,182 @@ BSC32=bscmake.exe
# ADD BASE BSC32 /nologo # ADD BASE BSC32 /nologo
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"Debug/libdb@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no # ADD LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_ASCII"
# PROP BASE Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_ASCII"
# PROP Intermediate_Dir "Debug_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /GX /Z7 /Od /I "." /I ".." /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /pdb:none /debug /machine:I386 /out:"@bin_debug_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win32 ASCII Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_ASCII"
# PROP BASE Intermediate_Dir "Release_ASCII/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_ASCII"
# PROP Intermediate_Dir "Release_ASCII/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /Ob2 /I "." /I ".." /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" @extra_cppflags@ /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:I386 /out:"@bin_rel_dest@_ASCII/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_AMD64"
# PROP BASE Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_AMD64"
# PROP Intermediate_Dir "Debug_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /FD /Wp64 /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:AMD64 /out:"@bin_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /debug /machine:AMD64 /out:"@bin_debug_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release AMD64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_AMD64"
# PROP BASE Intermediate_Dir "Release_AMD64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_AMD64"
# PROP Intermediate_Dir "Release_AMD64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:AMD64 /out:"@bin_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:AMD64 /out:"@bin_rel_dest@_AMD64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Debug IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "@lib_debug_dest@_IA64"
# PROP BASE Intermediate_Dir "Debug_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "@lib_debug_dest@_IA64"
# PROP Intermediate_Dir "Debug_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# SUBTRACT BASE CPP /Fr
# ADD CPP /nologo /MDd /W3 /EHsc /Z7 /Od /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "DIAGNOSTIC" /D "CONFIG_TEST" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# SUBTRACT CPP /Fr
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /debug /machine:IA64 /out:"@bin_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no
# ADD LINK32 @debug_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /export:__db_assert /debug /machine:IA64 /out:"@bin_debug_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@d.dll" /fixed:no /libpath:"$(OUTDIR)"
@POST_BUILD@
!ELSEIF "$(CFG)" == "@project_name@ - Win64 Release IA64"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "@lib_rel_dest@_IA64"
# PROP BASE Intermediate_Dir "Release_IA64/@project_name@"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "@lib_rel_dest@_IA64"
# PROP Intermediate_Dir "Release_IA64/@project_name@"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD CPP /nologo /MD /W3 /EHsc /O2 /Ob2 /I "." /I ".." /D "UNICODE" /D "_UNICODE" /D "DB_CREATE_DLL" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" @extra_cppflags@ /Wp64 /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o "NUL" /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"@bin_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll"
# ADD LINK32 @release_libs@ bufferoverflowU.lib kernel32.lib user32.lib advapi32.lib shell32.lib /nologo /base:"0x13000000" /subsystem:windows /dll /machine:IA64 /out:"@bin_rel_dest@_IA64/libdb@lib_suffix@@DB_VERSION_MAJOR@@DB_VERSION_MINOR@.dll" /libpath:"$(OUTDIR)"
@POST_BUILD@
!ENDIF !ENDIF
@ -88,6 +269,13 @@ LINK32=link.exe
# Name "@project_name@ - Win32 Release" # Name "@project_name@ - Win32 Release"
# Name "@project_name@ - Win32 Debug" # Name "@project_name@ - Win32 Debug"
# Name "@project_name@ - Win32 ASCII Debug"
# Name "@project_name@ - Win32 ASCII Release"
# Name "@project_name@ - Win64 Debug AMD64"
# Name "@project_name@ - Win64 Release AMD64"
# Name "@project_name@ - Win64 Debug IA64"
# Name "@project_name@ - Win64 Release IA64"
@SOURCE_FILES@ @SOURCE_FILES@
# End Target # End Target
# End Project # End Project

View file

@ -1,4 +1,4 @@
; $Id: libdb_tcl.def,v 11.7 2002/10/14 23:44:20 mjc Exp $ ; $Id: libdb_tcl.def,v 12.0 2004/11/17 03:48:15 bostic Exp $
DESCRIPTION 'Berkeley DB TCL interface Library' DESCRIPTION 'Berkeley DB TCL interface Library'
EXPORTS EXPORTS

Some files were not shown because too many files have changed in this diff Show more