transactd 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/BUILD_UNIX-JA +174 -0
- data/BUILD_WIN-JA +256 -0
- data/CMakeLists.txt +96 -0
- data/COPYING +339 -0
- data/README +406 -0
- data/README-JA +424 -0
- data/bin/common/tdclc_32_1_0.dll +0 -0
- data/bin/common/tdclc_64_1_0.dll +0 -0
- data/build/common/check_for_link_iconv.cmake +73 -0
- data/build/common/copyifgreater.cmd +30 -0
- data/build/common/copyifgreater.js +290 -0
- data/build/common/get_boost_libs.cmake +106 -0
- data/build/common/get_ruby_path.cmake +115 -0
- data/build/common/options.cmake +127 -0
- data/build/common/smart_install.cmake +263 -0
- data/build/common/system.cmake +122 -0
- data/build/common/transactd.rc.in +52 -0
- data/build/common/transactd_cl_common.cmake +101 -0
- data/build/common/transactd_cl_output.cmake +93 -0
- data/build/common/transactd_common.cmake +237 -0
- data/build/common/transactd_required.cmake +28 -0
- data/build/swig/ruby/generate.cmake.in +35 -0
- data/build/swig/ruby/generate.cmd.in +19 -0
- data/build/swig/ruby/ruby.swg +101 -0
- data/build/swig/tdcl.i +188 -0
- data/build/tdclc/BUILDNUMBER.txt +1 -0
- data/build/tdclc/CMakeLists.txt +170 -0
- data/build/tdclc/tdclc_32.cbproj +181 -0
- data/build/tdclc/tdclc_64.cbproj +205 -0
- data/build/tdclcpp/BUILDNUMBER.txt +1 -0
- data/build/tdclcpp/CMakeLists.txt +142 -0
- data/build/tdclcpp/tdclcpp_bcb_32.cbproj +239 -0
- data/build/tdclcpp/tdclcpp_bcb_64.cbproj +304 -0
- data/build/tdclrb/BUILDNUMBER.txt +1 -0
- data/build/tdclrb/CMakeLists.txt +258 -0
- data/build/tdclrb/GEM_VERSION +3 -0
- data/build/tdclrb/bldgem/extconf.rb +123 -0
- data/build/tdclrb/gem/INSTALLLOG.win32 +9 -0
- data/build/tdclrb/gem/Makefile.win32-VS +65 -0
- data/build/tdclrb/gem/Makefile.win32-prebuilt +48 -0
- data/build/tdclrb/gem/detect.rb +31 -0
- data/build/tdclrb/gem/helper.rb +113 -0
- data/build/tdclrb/gem/transactd.rb +22 -0
- data/build/tdclrb/gem_output.cmake +44 -0
- data/source/bzs/db/IBlobBuffer.h +51 -0
- data/source/bzs/db/blobBuffer.h +177 -0
- data/source/bzs/db/blobStructs.h +85 -0
- data/source/bzs/db/engine/mysql/IReadRecords.h +52 -0
- data/source/bzs/db/engine/mysql/bookmark.h +195 -0
- data/source/bzs/db/engine/mysql/database.cpp +1882 -0
- data/source/bzs/db/engine/mysql/database.h +465 -0
- data/source/bzs/db/engine/mysql/dbManager.cpp +303 -0
- data/source/bzs/db/engine/mysql/dbManager.h +143 -0
- data/source/bzs/db/engine/mysql/errorMessage.cpp +75 -0
- data/source/bzs/db/engine/mysql/errorMessage.h +43 -0
- data/source/bzs/db/engine/mysql/fieldAccess.h +158 -0
- data/source/bzs/db/engine/mysql/mydebuglog.cpp +349 -0
- data/source/bzs/db/engine/mysql/mydebuglog.h +89 -0
- data/source/bzs/db/engine/mysql/mysqlInternal.h +171 -0
- data/source/bzs/db/engine/mysql/mysqlThd.cpp +169 -0
- data/source/bzs/db/engine/mysql/mysqlThd.h +35 -0
- data/source/bzs/db/engine/mysql/percentageKey.h +260 -0
- data/source/bzs/db/protocol/ICommandExecuter.h +49 -0
- data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +689 -0
- data/source/bzs/db/protocol/hs/hsCommandExecuter.h +228 -0
- data/source/bzs/db/protocol/tdap/btrDate.cpp +437 -0
- data/source/bzs/db/protocol/tdap/btrDate.h +227 -0
- data/source/bzs/db/protocol/tdap/client/bulkInsert.h +127 -0
- data/source/bzs/db/protocol/tdap/client/client.cpp +106 -0
- data/source/bzs/db/protocol/tdap/client/client.h +292 -0
- data/source/bzs/db/protocol/tdap/client/connMgr.cpp +144 -0
- data/source/bzs/db/protocol/tdap/client/connMgr.h +82 -0
- data/source/bzs/db/protocol/tdap/client/database.cpp +863 -0
- data/source/bzs/db/protocol/tdap/client/database.h +118 -0
- data/source/bzs/db/protocol/tdap/client/databaseFactory.cpp +100 -0
- data/source/bzs/db/protocol/tdap/client/dbDef.cpp +1640 -0
- data/source/bzs/db/protocol/tdap/client/dbDef.h +135 -0
- data/source/bzs/db/protocol/tdap/client/dllmain.cpp +434 -0
- data/source/bzs/db/protocol/tdap/client/errorMessage.cpp +92 -0
- data/source/bzs/db/protocol/tdap/client/errorMessage_ja.cpp +98 -0
- data/source/bzs/db/protocol/tdap/client/fieldDDF.cpp +174 -0
- data/source/bzs/db/protocol/tdap/client/fieldDDF.h +91 -0
- data/source/bzs/db/protocol/tdap/client/fileDDF.cpp +140 -0
- data/source/bzs/db/protocol/tdap/client/fileDDF.h +86 -0
- data/source/bzs/db/protocol/tdap/client/filter.cpp +527 -0
- data/source/bzs/db/protocol/tdap/client/filter.h +154 -0
- data/source/bzs/db/protocol/tdap/client/indexDDF.cpp +137 -0
- data/source/bzs/db/protocol/tdap/client/indexDDF.h +84 -0
- data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +724 -0
- data/source/bzs/db/protocol/tdap/client/nsDatabase.h +123 -0
- data/source/bzs/db/protocol/tdap/client/nsTable.cpp +899 -0
- data/source/bzs/db/protocol/tdap/client/nsTable.h +199 -0
- data/source/bzs/db/protocol/tdap/client/request.h +198 -0
- data/source/bzs/db/protocol/tdap/client/sharedData.cpp +58 -0
- data/source/bzs/db/protocol/tdap/client/sharedData.h +56 -0
- data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +574 -0
- data/source/bzs/db/protocol/tdap/client/sqlBuilder.h +53 -0
- data/source/bzs/db/protocol/tdap/client/stringConverter.h +627 -0
- data/source/bzs/db/protocol/tdap/client/table.cpp +2613 -0
- data/source/bzs/db/protocol/tdap/client/table.h +221 -0
- data/source/bzs/db/protocol/tdap/client/trdboostapi.h +1096 -0
- data/source/bzs/db/protocol/tdap/client/trdboostapiInternal.h +179 -0
- data/source/bzs/db/protocol/tdap/client/trdclcppautolink.h +40 -0
- data/source/bzs/db/protocol/tdap/client/trnsctcl.def +11 -0
- data/source/bzs/db/protocol/tdap/myDateTime.cpp +500 -0
- data/source/bzs/db/protocol/tdap/mysql/characterset.cpp +184 -0
- data/source/bzs/db/protocol/tdap/mysql/characterset.h +60 -0
- data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +284 -0
- data/source/bzs/db/protocol/tdap/mysql/databaseSchema.h +53 -0
- data/source/bzs/db/protocol/tdap/mysql/debuglog.cpp +383 -0
- data/source/bzs/db/protocol/tdap/mysql/debuglog.h +106 -0
- data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +680 -0
- data/source/bzs/db/protocol/tdap/mysql/request.h +202 -0
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +1020 -0
- data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +141 -0
- data/source/bzs/db/protocol/tdap/tdapRequest.h +190 -0
- data/source/bzs/db/protocol/tdap/tdapSchema.cpp +295 -0
- data/source/bzs/db/protocol/tdap/tdapSchema.h +558 -0
- data/source/bzs/db/protocol/tdap/tdapcapi.h +423 -0
- data/source/bzs/db/transactd/appBuilderImple.h +55 -0
- data/source/bzs/db/transactd/appModule.cpp +183 -0
- data/source/bzs/db/transactd/appModule.h +80 -0
- data/source/bzs/db/transactd/connManager.cpp +201 -0
- data/source/bzs/db/transactd/connManager.h +60 -0
- data/source/bzs/db/transactd/connectionRecord.h +69 -0
- data/source/bzs/db/transactd/transactd.cpp +325 -0
- data/source/bzs/env/compiler.h +135 -0
- data/source/bzs/env/crosscompile.cpp +130 -0
- data/source/bzs/env/crosscompile.h +150 -0
- data/source/bzs/env/fileopen.h +36 -0
- data/source/bzs/env/mbcswchrLinux.cpp +40 -0
- data/source/bzs/env/mbcswchrLinux.h +88 -0
- data/source/bzs/env/tstring.h +183 -0
- data/source/bzs/example/changeSchema.cpp +117 -0
- data/source/bzs/example/changeSchema_c.cpp +78 -0
- data/source/bzs/example/connection_pool_c.cpp +171 -0
- data/source/bzs/example/createDatabase.cpp +305 -0
- data/source/bzs/example/createDatabase_c.cpp +202 -0
- data/source/bzs/example/deleteRecords.cpp +87 -0
- data/source/bzs/example/deleteRecords_c.cpp +57 -0
- data/source/bzs/example/dropDatabase.cpp +59 -0
- data/source/bzs/example/dropDatabase_c.cpp +34 -0
- data/source/bzs/example/insertRecords.cpp +212 -0
- data/source/bzs/example/insertRecords_c.cpp +153 -0
- data/source/bzs/example/readRecords.cpp +141 -0
- data/source/bzs/example/readRecords_c.cpp +107 -0
- data/source/bzs/example/updateRecords.cpp +99 -0
- data/source/bzs/example/updateRecords_c.cpp +71 -0
- data/source/bzs/example/update_with_transaction.cpp +104 -0
- data/source/bzs/example/update_with_transaction_c.cpp +80 -0
- data/source/bzs/netsvc/client/tcpClient.cpp +226 -0
- data/source/bzs/netsvc/client/tcpClient.h +489 -0
- data/source/bzs/netsvc/server/IAppModule.h +94 -0
- data/source/bzs/netsvc/server/iserver.h +65 -0
- data/source/bzs/netsvc/server/serverCpt.cpp +522 -0
- data/source/bzs/netsvc/server/serverCpt.h +88 -0
- data/source/bzs/netsvc/server/serverPipe.cpp +705 -0
- data/source/bzs/netsvc/server/serverPipe.h +96 -0
- data/source/bzs/netsvc/server/serverTpool.cpp +416 -0
- data/source/bzs/netsvc/server/serverTpool.h +84 -0
- data/source/bzs/rtl/benchmark.cpp +96 -0
- data/source/bzs/rtl/benchmark.h +65 -0
- data/source/bzs/rtl/datetime.cpp +375 -0
- data/source/bzs/rtl/datetime.h +53 -0
- data/source/bzs/rtl/debuglog.cpp +106 -0
- data/source/bzs/rtl/debuglog.h +97 -0
- data/source/bzs/rtl/exception.h +116 -0
- data/source/bzs/rtl/stl_uty.cpp +35 -0
- data/source/bzs/rtl/stl_uty.h +29 -0
- data/source/bzs/rtl/stringBuffers.cpp +101 -0
- data/source/bzs/rtl/stringBuffers.h +58 -0
- data/source/bzs/rtl/strtrim.cpp +135 -0
- data/source/bzs/rtl/strtrim.h +46 -0
- data/source/bzs/test/tdclatl/bench_tdclatl.js +445 -0
- data/source/bzs/test/tdclrb/bench_tdclcpp.rb +375 -0
- data/source/bzs/test/tdclrb/prepare.rb +226 -0
- data/source/bzs/test/tdclrb/transactd_datetime_spec.rb +172 -0
- data/source/bzs/test/tdclrb/transactd_kanjischema_spec.rb +208 -0
- data/source/bzs/test/tdclrb/transactd_spec.rb +1536 -0
- data/source/bzs/test/transactdBench/transactdBench.cpp +430 -0
- data/source/bzs/test/transactdBench/transactdBench2.cpp +342 -0
- data/source/bzs/test/trdclengn/test_trdclengn.cpp +2030 -0
- data/source/global/tdclatl/Database.cpp +503 -0
- data/source/global/tdclatl/Database.h +139 -0
- data/source/global/tdclatl/DbDef.cpp +242 -0
- data/source/global/tdclatl/DbDef.h +79 -0
- data/source/global/tdclatl/Field.cpp +92 -0
- data/source/global/tdclatl/Field.h +59 -0
- data/source/global/tdclatl/FieldDef.cpp +238 -0
- data/source/global/tdclatl/FieldDef.h +87 -0
- data/source/global/tdclatl/Flags.cpp +111 -0
- data/source/global/tdclatl/Flags.h +55 -0
- data/source/global/tdclatl/KeyDef.cpp +51 -0
- data/source/global/tdclatl/KeyDef.h +55 -0
- data/source/global/tdclatl/KeySegment.cpp +55 -0
- data/source/global/tdclatl/Table.cpp +600 -0
- data/source/global/tdclatl/Table.h +144 -0
- data/source/global/tdclatl/TableDef.cpp +291 -0
- data/source/global/tdclatl/TableDef.h +86 -0
- data/source/global/tdclatl/TdVersion.cpp +74 -0
- data/source/global/tdclatl/TdVersion.h +54 -0
- data/source/global/tdclatl/_IDatabaseEvents_CP.h +113 -0
- data/source/global/tdclatl/dllmain.cpp +30 -0
- data/source/global/tdclatl/dllmain.h +27 -0
- data/source/global/tdclatl/keySegment.h +57 -0
- data/source/global/tdclatl/resource.h +0 -0
- data/source/global/tdclatl/stdafx.cpp +2 -0
- data/source/global/tdclatl/stdafx.h +25 -0
- data/source/global/tdclatl/targetver.h +4 -0
- data/source/global/tdclatl/tdclatl.cpp +68 -0
- data/source/global/tdclatl/tdclatl.def +10 -0
- data/source/global/tdclatl/tdclatl.idl +1035 -0
- data/source/linux/charsetConvert.h +112 -0
- data/source/linux/linuxTypes.h +33 -0
- data/source/linux/tchar.h +428 -0
- data/transactd.gemspec +97 -0
- metadata +267 -0
|
@@ -0,0 +1,1882 @@
|
|
|
1
|
+
/*=================================================================
|
|
2
|
+
Copyright (C) 2012 2013 BizStation Corp All rights reserved.
|
|
3
|
+
|
|
4
|
+
This program is free software; you can redistribute it and/or
|
|
5
|
+
modify it under the terms of the GNU General Public License
|
|
6
|
+
as published by the Free Software Foundation; either version 2
|
|
7
|
+
of the License, or (at your option) any later version.
|
|
8
|
+
|
|
9
|
+
This program is distributed in the hope that it will be useful,
|
|
10
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
GNU General Public License for more details.
|
|
13
|
+
|
|
14
|
+
You should have received a copy of the GNU General Public License
|
|
15
|
+
along with this program; if not, write to the Free Software
|
|
16
|
+
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
17
|
+
02111-1307, USA.
|
|
18
|
+
=================================================================*/
|
|
19
|
+
|
|
20
|
+
#include "database.h"
|
|
21
|
+
#include <boost/bind.hpp>
|
|
22
|
+
#include "IReadRecords.h"
|
|
23
|
+
#include "percentageKey.h"
|
|
24
|
+
|
|
25
|
+
#include "mydebuglog.h"
|
|
26
|
+
|
|
27
|
+
#include "mysqlThd.h"
|
|
28
|
+
#include "bookmark.h"
|
|
29
|
+
#include <bzs/rtl/stl_uty.h>
|
|
30
|
+
#include <boost/shared_array.hpp>
|
|
31
|
+
|
|
32
|
+
extern int g_useBtrvVariableTable;
|
|
33
|
+
namespace bzs
|
|
34
|
+
{
|
|
35
|
+
namespace db
|
|
36
|
+
{
|
|
37
|
+
namespace engine
|
|
38
|
+
{
|
|
39
|
+
namespace mysql
|
|
40
|
+
{
|
|
41
|
+
|
|
42
|
+
using namespace std;
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
unsigned int hash(const char *s, size_t len)
|
|
46
|
+
{
|
|
47
|
+
unsigned int h = 0;
|
|
48
|
+
for (size_t i=0;i < len; i++)
|
|
49
|
+
h = h * 137 + *(s+i);
|
|
50
|
+
return h % 1987;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
tableCacheCounter::tableCacheCounter()
|
|
54
|
+
{
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
int tableCacheCounter::getHash(const std::string& dbname, const std::string& tbname)
|
|
59
|
+
{
|
|
60
|
+
char tmp[256];
|
|
61
|
+
sprintf_s(tmp, 256,"%s%s",dbname.c_str(), tbname.c_str());
|
|
62
|
+
return hash(tmp, strlen(tmp));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
size_t tableCacheCounter::getCounterIndex(const std::string& dbname, const std::string& tbname)
|
|
66
|
+
{
|
|
67
|
+
int h = getHash(dbname, tbname);
|
|
68
|
+
vector<int>::iterator pos = find(m_tables.begin(),m_tables.end(), h);
|
|
69
|
+
if (pos == m_tables.end())
|
|
70
|
+
{
|
|
71
|
+
m_tables.push_back(h);
|
|
72
|
+
m_counts.push_back(0);
|
|
73
|
+
return m_counts.size() - 1;
|
|
74
|
+
}
|
|
75
|
+
return pos - m_tables.begin();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void tableCacheCounter::addref(const std::string& dbname, const std::string& tbname)
|
|
79
|
+
{
|
|
80
|
+
|
|
81
|
+
boost::mutex::scoped_lock lck(m_mutex);
|
|
82
|
+
size_t pos = getCounterIndex(dbname, tbname);
|
|
83
|
+
++m_counts[pos];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
int tableCacheCounter::count(const std::string& dbname, const std::string& tbname)
|
|
87
|
+
{
|
|
88
|
+
boost::mutex::scoped_lock lck(m_mutex);
|
|
89
|
+
size_t pos = getCounterIndex(dbname, tbname);
|
|
90
|
+
return m_counts[pos];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
void tableCacheCounter::release(const std::string& dbname, const std::string& tbname)
|
|
94
|
+
{
|
|
95
|
+
boost::mutex::scoped_lock lck(m_mutex);
|
|
96
|
+
size_t pos = getCounterIndex(dbname, tbname);
|
|
97
|
+
--m_counts[pos];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#define KEYLEN_ALLCOPY 0
|
|
101
|
+
#define OPEN_TABLE_TIMEOUT_SEC 2
|
|
102
|
+
|
|
103
|
+
void lockTable(THD* thd, TABLE* tb)
|
|
104
|
+
{
|
|
105
|
+
bool append = (thd->lock!=0);
|
|
106
|
+
thd->in_lock_tables = 1;
|
|
107
|
+
MYSQL_LOCK *lockMrg=NULL;
|
|
108
|
+
|
|
109
|
+
MYSQL_LOCK *lock = mysql_lock_tables(thd, &tb, 1, 0);
|
|
110
|
+
if (!append)
|
|
111
|
+
thd->lock = lock;
|
|
112
|
+
else if (lock)
|
|
113
|
+
{
|
|
114
|
+
MYSQL_LOCK *lockMrg = mysql_lock_merge(thd->lock, lock);
|
|
115
|
+
if (lockMrg)
|
|
116
|
+
thd->lock= lockMrg;
|
|
117
|
+
}
|
|
118
|
+
thd->in_lock_tables= 0;
|
|
119
|
+
DEBUG_WRITELOG_SP1("LOCK TABLE table =%s\n", tb->s->table_name.str);
|
|
120
|
+
|
|
121
|
+
return ;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** The present lock type is returned.
|
|
125
|
+
* The true lock type of innodb is controlled by m_thd->lex->sql_command.
|
|
126
|
+
*/
|
|
127
|
+
thr_lock_type locktype(bool trn, enum_sql_command cmd)
|
|
128
|
+
{
|
|
129
|
+
if (trn)
|
|
130
|
+
return TL_WRITE;
|
|
131
|
+
thr_lock_type lock_type = TL_READ;
|
|
132
|
+
switch(cmd)
|
|
133
|
+
{
|
|
134
|
+
case SQLCOM_INSERT:
|
|
135
|
+
case SQLCOM_DELETE:
|
|
136
|
+
case SQLCOM_UPDATE:
|
|
137
|
+
case SQLCOM_DROP_TABLE:
|
|
138
|
+
case SQLCOM_CREATE_TABLE:
|
|
139
|
+
case SQLCOM_CREATE_INDEX:
|
|
140
|
+
lock_type = TL_WRITE;
|
|
141
|
+
default:
|
|
142
|
+
;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return lock_type;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
bool unlockTables(bool releaseStatementLock, THD* thd, bool rollback)
|
|
149
|
+
{
|
|
150
|
+
if (thd->lock)
|
|
151
|
+
{
|
|
152
|
+
bool ret;
|
|
153
|
+
if (rollback)
|
|
154
|
+
ret = trans_rollback_stmt(thd);
|
|
155
|
+
else
|
|
156
|
+
ret = trans_commit_stmt(thd);
|
|
157
|
+
if (releaseStatementLock)
|
|
158
|
+
thd->mdl_context.release_statement_locks();
|
|
159
|
+
mysql_unlock_tables(thd, thd->lock);
|
|
160
|
+
thd->lock = 0;
|
|
161
|
+
return !ret;
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
#ifdef _MSC_VER
|
|
168
|
+
#pragma warning(disable:4355)
|
|
169
|
+
#endif
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
bool g_safe_share_mode=false;
|
|
173
|
+
tableCacheCounter database::tableRef;
|
|
174
|
+
|
|
175
|
+
database::database(const char* name, short cid)
|
|
176
|
+
:m_dbname(name),m_thd(createThdForThread()),m_cid(cid)
|
|
177
|
+
,m_inTransaction(0),m_inSnapshot(0),m_trnType(0)
|
|
178
|
+
{
|
|
179
|
+
m_thd->security_ctx->skip_grants();
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
#ifdef _MSC_VER
|
|
187
|
+
#pragma warning(default:4355)
|
|
188
|
+
#endif
|
|
189
|
+
|
|
190
|
+
database::~database()
|
|
191
|
+
{
|
|
192
|
+
use();
|
|
193
|
+
unUseTables(false);
|
|
194
|
+
closeForReopen();
|
|
195
|
+
m_tables.clear();//It clears ahead of the destructor of m_trn.
|
|
196
|
+
deleteThdForThread(m_thd);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
void database::use() const
|
|
200
|
+
{
|
|
201
|
+
attachThd(m_thd);
|
|
202
|
+
m_thd->clear_error();
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// locktable
|
|
206
|
+
table* database::useTable(int index, enum_sql_command cmd)
|
|
207
|
+
{
|
|
208
|
+
if (index>=(int)m_tables.size())
|
|
209
|
+
THROW_BZS_ERROR_WITH_CODEMSG(1, "Invalid table id.");
|
|
210
|
+
|
|
211
|
+
table* tb = m_tables[index].get();
|
|
212
|
+
if (tb == NULL)
|
|
213
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_FILE_NOT_OPENED, "Invalid table id.");
|
|
214
|
+
|
|
215
|
+
if (tb->m_blobBuffer)
|
|
216
|
+
tb->m_blobBuffer->clear();
|
|
217
|
+
if (tb->islocked())
|
|
218
|
+
{
|
|
219
|
+
if (tb->m_table==NULL)
|
|
220
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_FILE_NOT_OPENED, "Invalid table id.");
|
|
221
|
+
return tb;
|
|
222
|
+
}
|
|
223
|
+
if (g_safe_share_mode && tb->m_table==NULL)
|
|
224
|
+
reopen();
|
|
225
|
+
if (tb->m_table==NULL)
|
|
226
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_FILE_NOT_OPENED, "Invalid table id.");
|
|
227
|
+
bool trn = (m_inTransaction>0) & (tb->mode() != TD_OPEN_READONLY);
|
|
228
|
+
tb->m_table->reginfo.lock_type = locktype(trn, cmd);
|
|
229
|
+
if ((tb->mode() == TD_OPEN_READONLY) && (tb->m_table->reginfo.lock_type == TL_WRITE))
|
|
230
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_ACCESS_DENIED, "Access denined.");
|
|
231
|
+
if (m_thd->lock==0)
|
|
232
|
+
{
|
|
233
|
+
m_thd->lex->sql_command = cmd;
|
|
234
|
+
m_thd->tx_isolation= (enum_tx_isolation) m_thd->variables.tx_isolation;
|
|
235
|
+
cp_thd_set_read_only(m_thd);
|
|
236
|
+
}
|
|
237
|
+
lockTable(m_thd, tb->m_table);
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
if ((tb->m_table->reginfo.lock_type == TL_WRITE) && (m_thd->variables.sql_log_bin))
|
|
241
|
+
m_thd->set_current_stmt_binlog_format_row();
|
|
242
|
+
tb->setLocked(true);
|
|
243
|
+
if (g_safe_share_mode)
|
|
244
|
+
{
|
|
245
|
+
tb->m_keyconv.setKey(tb->m_table->key_info);
|
|
246
|
+
if (tb->keyNum()>=0)
|
|
247
|
+
tb->m_table->file->ha_index_init(tb->keyNum(), 1/*sorted*/);
|
|
248
|
+
else if(tb->keyNum() == -2)
|
|
249
|
+
tb->m_table->file->ha_rnd_init(false);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return tb;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
void database::unUseTable(table* tb)
|
|
256
|
+
{
|
|
257
|
+
if (tb->islocked() && (m_inTransaction + m_inSnapshot==0))
|
|
258
|
+
{ //Only this table is lock release.
|
|
259
|
+
bool needUnlock = (locktype(false, m_thd->lex->sql_command)==TL_WRITE);
|
|
260
|
+
bool changed = tb->isChanged();
|
|
261
|
+
tb->resetTransctionInfo(m_thd);
|
|
262
|
+
bool rollback = (!changed && needUnlock);
|
|
263
|
+
if (unlockTables(needUnlock, m_thd, rollback))
|
|
264
|
+
{
|
|
265
|
+
DEBUG_WRITELOG_SP1("UNLOCK TABLE table =%s\n", tb->m_table->s->table_name.str);
|
|
266
|
+
}else
|
|
267
|
+
{
|
|
268
|
+
DEBUG_WRITELOG_SP1("UNLOCK TABLE ERROR table =%s\n", tb->m_table->s->table_name.str);
|
|
269
|
+
if (m_thd->is_error())
|
|
270
|
+
{
|
|
271
|
+
|
|
272
|
+
if (ER_LOCK_WAIT_TIMEOUT == m_thd->cp_get_sql_error())
|
|
273
|
+
m_stat = STATUS_CANNOT_LOCK_TABLE;
|
|
274
|
+
else
|
|
275
|
+
m_stat = m_thd->cp_get_sql_error();
|
|
276
|
+
THROW_BZS_ERROR_WITH_CODEMSG(m_stat, "Transaction commit error.");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (g_safe_share_mode)
|
|
280
|
+
{
|
|
281
|
+
unUseTables(false);
|
|
282
|
+
closeForReopen();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
void database::unUseTables(bool rollback)
|
|
289
|
+
{
|
|
290
|
+
//All the table lock release
|
|
291
|
+
bool needUnlock = (locktype((m_inTransaction>0), m_thd->lex->sql_command)==TL_WRITE);
|
|
292
|
+
m_inTransaction = 0;
|
|
293
|
+
m_inSnapshot = 0;
|
|
294
|
+
for (int i=0;i<(int)m_tables.size();i++)
|
|
295
|
+
{
|
|
296
|
+
if (m_tables[i])
|
|
297
|
+
m_tables[i]->resetTransctionInfo(m_thd);
|
|
298
|
+
}
|
|
299
|
+
if (unlockTables(needUnlock, m_thd, rollback))
|
|
300
|
+
{
|
|
301
|
+
DEBUG_WRITELOG("UNLOCK TABLES \n")
|
|
302
|
+
}
|
|
303
|
+
else
|
|
304
|
+
{
|
|
305
|
+
if (m_thd->is_error())
|
|
306
|
+
{
|
|
307
|
+
DEBUG_WRITELOG("UNLOCK TABLES ERROR \n");
|
|
308
|
+
if (ER_LOCK_WAIT_TIMEOUT == m_thd->cp_get_sql_error())
|
|
309
|
+
m_stat = STATUS_CANNOT_LOCK_TABLE;
|
|
310
|
+
else
|
|
311
|
+
m_stat = m_thd->cp_get_sql_error();
|
|
312
|
+
THROW_BZS_ERROR_WITH_CODEMSG(m_stat, "Transaction commit error.");
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (g_safe_share_mode)
|
|
316
|
+
closeForReopen();
|
|
317
|
+
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
bool database::beginTrn(short type)
|
|
321
|
+
{
|
|
322
|
+
++m_inTransaction;
|
|
323
|
+
if (m_inTransaction == 1)
|
|
324
|
+
{
|
|
325
|
+
m_trnType = type;
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
bool database::commitTrn()
|
|
332
|
+
{
|
|
333
|
+
if (m_inTransaction>0)
|
|
334
|
+
{
|
|
335
|
+
--m_inTransaction;
|
|
336
|
+
if (m_inTransaction==0)
|
|
337
|
+
unUseTables(false);
|
|
338
|
+
}
|
|
339
|
+
return (m_inTransaction == 0);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
bool database::abortTrn()
|
|
343
|
+
{
|
|
344
|
+
if (m_inTransaction>0)
|
|
345
|
+
{
|
|
346
|
+
--m_inTransaction;
|
|
347
|
+
if (m_inTransaction==0)
|
|
348
|
+
unUseTables(true);
|
|
349
|
+
}
|
|
350
|
+
return (m_inTransaction == 0);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
bool database::beginSnapshot()
|
|
354
|
+
{
|
|
355
|
+
++m_inSnapshot;
|
|
356
|
+
return (m_inSnapshot == 1);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
bool database::endSnapshot()
|
|
360
|
+
{
|
|
361
|
+
if (m_inSnapshot>0)
|
|
362
|
+
{
|
|
363
|
+
--m_inSnapshot;
|
|
364
|
+
if (m_inSnapshot==0)
|
|
365
|
+
unUseTables(false);
|
|
366
|
+
}
|
|
367
|
+
return (m_inSnapshot == 0);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** Metadata lock, a table name is case-sensitive
|
|
371
|
+
* However, in actual opening, it is not distinguished at Windows.
|
|
372
|
+
*/
|
|
373
|
+
TABLE* database::doOpenTable(const std::string& name, short mode)
|
|
374
|
+
{
|
|
375
|
+
TABLE_LIST tables;
|
|
376
|
+
m_thd->variables.lock_wait_timeout = OPEN_TABLE_TIMEOUT_SEC;
|
|
377
|
+
tables.init_one_table(m_dbname.c_str(), m_dbname.size(), name.c_str(), name.size(), name.c_str(), TL_READ);
|
|
378
|
+
Open_table_context ot_act(m_thd, 0);
|
|
379
|
+
if (mode == TD_OPEN_EXCLUSIVE)
|
|
380
|
+
tables.mdl_request.set_type(MDL_EXCLUSIVE);
|
|
381
|
+
else
|
|
382
|
+
tables.mdl_request.set_type(MDL_SHARED_READ);
|
|
383
|
+
|
|
384
|
+
if (cp_open_table(m_thd, &tables, &ot_act))
|
|
385
|
+
{
|
|
386
|
+
m_stat = STATUS_TABLE_NOTOPEN;
|
|
387
|
+
if (ER_LOCK_WAIT_TIMEOUT == m_thd->cp_get_sql_error())
|
|
388
|
+
m_stat = STATUS_CANNOT_LOCK_TABLE;
|
|
389
|
+
THROW_BZS_ERROR_WITH_CODEMSG(m_stat, name.c_str());
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
tables.table->use_all_columns();
|
|
393
|
+
tables.table->open_by_handler = 1;
|
|
394
|
+
#if (defined(DEBUG) && defined(WIN32))
|
|
395
|
+
char buf[10];
|
|
396
|
+
sprintf(buf, "%d", tables.table->field[1]->key_length());
|
|
397
|
+
OutputDebugString(buf);
|
|
398
|
+
#endif
|
|
399
|
+
return tables.table;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
table* database::openTable(const std::string& name, short mode)
|
|
403
|
+
{
|
|
404
|
+
if (existsTable(name))
|
|
405
|
+
{
|
|
406
|
+
tableRef.addref(m_dbname, name);//addef first then table open.
|
|
407
|
+
boost::shared_ptr<table> tb(new table(doOpenTable(name, mode) , *this, name, mode, (int)m_tables.size()));
|
|
408
|
+
m_tables.push_back(tb);
|
|
409
|
+
m_stat = STATUS_SUCCESS;
|
|
410
|
+
return tb.get();
|
|
411
|
+
}
|
|
412
|
+
m_stat = STATUS_TABLE_NOTOPEN;
|
|
413
|
+
THROW_BZS_ERROR_WITH_CODEMSG(m_stat, name.c_str());
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
void database::closeTable(const std::string& name, bool drop)
|
|
417
|
+
{
|
|
418
|
+
for (int i=(int)m_tables.size()-1;i>=0;i--)
|
|
419
|
+
{
|
|
420
|
+
if (m_tables[i] && (m_tables[i]->m_name == name))
|
|
421
|
+
{
|
|
422
|
+
m_tables[i].reset();
|
|
423
|
+
DEBUG_WRITELOG_SP1("CLOSE TABLE table id=%d \n", i);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
void database::closeTable(table* tb)
|
|
429
|
+
{
|
|
430
|
+
for (int i=(int)m_tables.size()-1;i>=0;i--)
|
|
431
|
+
{
|
|
432
|
+
if (m_tables[i] && (m_tables[i].get() == tb))
|
|
433
|
+
{
|
|
434
|
+
m_tables[i].reset();
|
|
435
|
+
DEBUG_WRITELOG_SP1("CLOSE TABLE table id=%d \n", i);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
void database::closeForReopen()
|
|
441
|
+
{
|
|
442
|
+
//A transaction is committed compulsorily.
|
|
443
|
+
|
|
444
|
+
for (size_t i=0;i<m_tables.size();i++)
|
|
445
|
+
{
|
|
446
|
+
if (m_tables[i] && (m_tables[i]->m_table!=NULL))
|
|
447
|
+
m_tables[i]->resetInternalTable(NULL);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
trans_commit_stmt(m_thd);
|
|
451
|
+
close_thread_tables(m_thd);
|
|
452
|
+
m_thd->mdl_context.release_transactional_locks();//It is certainly after close_thread_tables.
|
|
453
|
+
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
void database::reopen()
|
|
457
|
+
{
|
|
458
|
+
for (size_t i=0;i<m_tables.size();i++)
|
|
459
|
+
{
|
|
460
|
+
if (m_tables[i] && (m_tables[i]->m_table==NULL))
|
|
461
|
+
{
|
|
462
|
+
TABLE* table = doOpenTable(m_tables[i]->m_name.c_str(), m_tables[i]->m_mode);
|
|
463
|
+
if (table)
|
|
464
|
+
m_tables[i]->resetInternalTable(table);
|
|
465
|
+
else
|
|
466
|
+
m_tables[i].reset();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
bool database::existsTable(const std::string& name)
|
|
472
|
+
{
|
|
473
|
+
char tmp[FN_REFLEN + 1];
|
|
474
|
+
|
|
475
|
+
build_table_filename(tmp, sizeof(tmp) - 1,
|
|
476
|
+
m_dbname.c_str(), name.c_str(), reg_ext, 0);
|
|
477
|
+
MY_STAT st;
|
|
478
|
+
if (mysql_file_stat(0, tmp, &st, MYF(0)))
|
|
479
|
+
return true;
|
|
480
|
+
return false;
|
|
481
|
+
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
bool database::existsDatabase()
|
|
485
|
+
{
|
|
486
|
+
char tmp[FN_REFLEN + 1];
|
|
487
|
+
size_t len = build_table_filename(tmp, sizeof(tmp) - 1, m_dbname.c_str(), "", "", 0);
|
|
488
|
+
tmp[len-1]= 0x00;
|
|
489
|
+
|
|
490
|
+
MY_STAT stat;
|
|
491
|
+
if (mysql_file_stat(0, tmp, &stat, MYF(0)))
|
|
492
|
+
return true;
|
|
493
|
+
return false;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
class autoincSetup
|
|
497
|
+
{
|
|
498
|
+
TABLE* m_table;
|
|
499
|
+
public:
|
|
500
|
+
autoincSetup(TABLE* table):m_table(table)
|
|
501
|
+
{
|
|
502
|
+
m_table->next_number_field = m_table->found_next_number_field;
|
|
503
|
+
}
|
|
504
|
+
~autoincSetup()
|
|
505
|
+
{
|
|
506
|
+
m_table->next_number_field = 0;
|
|
507
|
+
}
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
/** Number of NIS fields
|
|
511
|
+
*/
|
|
512
|
+
unsigned short nisFieldNum(TABLE* tb)
|
|
513
|
+
{
|
|
514
|
+
if (tb->s->null_fields)
|
|
515
|
+
{
|
|
516
|
+
int offset= 1;
|
|
517
|
+
|
|
518
|
+
for (unsigned int i=tb->s->fields-offset;i>=0;--i)
|
|
519
|
+
if (isNisField(tb->s->field[i]->field_name)==false)
|
|
520
|
+
return (unsigned short)(tb->s->fields - i - offset);
|
|
521
|
+
return tb->s->fields;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
return 0;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
bool table::noKeybufResult = true;
|
|
528
|
+
|
|
529
|
+
table::table(TABLE* myTable, database& db, const std::string& name, short mode, int id)
|
|
530
|
+
:m_table(myTable),m_db(db),m_name(name), m_mode(mode),m_blobBuffer(NULL)
|
|
531
|
+
,m_id(id),m_keyNum(-1),m_stat(0)
|
|
532
|
+
,m_validCursor(true),m_cursor(false)
|
|
533
|
+
,m_keybuf(new unsigned char[MAX_KEYLEN])
|
|
534
|
+
,m_nonNccKeybuf(new unsigned char[MAX_KEYLEN])
|
|
535
|
+
,m_nonNcc(false),m_bulkInserting(false)
|
|
536
|
+
,m_keyconv(m_table->key_info, m_table->s->keys)
|
|
537
|
+
,m_locked(false),m_changed(false),m_nounlock(false)
|
|
538
|
+
|
|
539
|
+
{
|
|
540
|
+
|
|
541
|
+
m_table->read_set = &m_table->s->all_set;
|
|
542
|
+
m_recordFormatType = RF_VALIABLE_LEN;
|
|
543
|
+
m_lastVarLenBytes = 0;
|
|
544
|
+
|
|
545
|
+
//Is the Nis field included or not?
|
|
546
|
+
m_nullFields = nisFieldNum(m_table);
|
|
547
|
+
|
|
548
|
+
if (m_table->s->varchar_fields + m_table->s->blob_fields == 0)
|
|
549
|
+
m_recordFormatType = RF_FIXED_LEN;
|
|
550
|
+
else if ((m_table->s->varchar_fields == 1) && g_useBtrvVariableTable)
|
|
551
|
+
{
|
|
552
|
+
Field** fd = m_table->field + lastVarFiledNum();
|
|
553
|
+
if (isVarType((*fd)->type()) && ((*fd)->part_of_key.is_clear_all()/* == Bitmap<64>()*/)
|
|
554
|
+
&& ((*fd)->key_start.is_clear_all()/* == Bitmap<64>()*/)
|
|
555
|
+
&& (((*fd)->charset()) == &my_charset_bin))
|
|
556
|
+
{
|
|
557
|
+
m_recordFormatType = RF_FIXED_PLUS_VALIABLE_LEN;
|
|
558
|
+
|
|
559
|
+
/* The number of bytes of the length area of the last VAR field */
|
|
560
|
+
m_lastVarLenBytes = lastVarFiled()->field_length < 256 ? 1:2;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
if (m_nullFields)
|
|
565
|
+
m_recordFormatType |= RF_INCLUDE_NIS;
|
|
566
|
+
m_recordLenCl = (uint)(m_table->s->reclength-(uint)(m_table->s->null_fields>0) - m_nullFields-m_lastVarLenBytes);
|
|
567
|
+
|
|
568
|
+
//Chash null field
|
|
569
|
+
if (m_table->s->null_fields)
|
|
570
|
+
{
|
|
571
|
+
for (int i=0;i<(int)m_table->s->fields;++i)
|
|
572
|
+
{
|
|
573
|
+
Field* fd = m_table->field[i];
|
|
574
|
+
if (fd->null_bit && fd->part_of_key.is_clear_all())
|
|
575
|
+
m_nonKeySegNullFields.push_back(fd);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
table::~table()
|
|
581
|
+
{
|
|
582
|
+
resetInternalTable(NULL);
|
|
583
|
+
database::tableRef.release(m_db.name(), m_name);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
void table::resetTransctionInfo(THD* thd)
|
|
587
|
+
{
|
|
588
|
+
if (m_table)
|
|
589
|
+
{
|
|
590
|
+
if (m_changed)
|
|
591
|
+
query_cache_invalidate3(thd, m_table, 1);
|
|
592
|
+
m_changed = false;
|
|
593
|
+
m_table->next_number_field = 0;
|
|
594
|
+
m_table->file->next_insert_id = 0;
|
|
595
|
+
}
|
|
596
|
+
m_locked = false;
|
|
597
|
+
m_validCursor = false;
|
|
598
|
+
m_nounlock = false;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
void table::resetInternalTable(TABLE* table)
|
|
602
|
+
{
|
|
603
|
+
if (table==NULL)
|
|
604
|
+
{
|
|
605
|
+
if (m_table)
|
|
606
|
+
m_table->file->ha_index_or_rnd_end();
|
|
607
|
+
m_table = NULL;
|
|
608
|
+
}else
|
|
609
|
+
{
|
|
610
|
+
m_table = table;
|
|
611
|
+
m_table->read_set = &m_table->s->all_set;
|
|
612
|
+
m_locked = false;
|
|
613
|
+
m_changed = false;
|
|
614
|
+
m_validCursor = false;
|
|
615
|
+
m_nounlock = false;
|
|
616
|
+
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
bool table::setNonKey(bool scan)
|
|
621
|
+
{
|
|
622
|
+
if (m_keyNum != -2)
|
|
623
|
+
{
|
|
624
|
+
m_table->file->ha_index_or_rnd_end();
|
|
625
|
+
m_table->file->ha_rnd_init(scan);
|
|
626
|
+
m_keyNum = -2;
|
|
627
|
+
}
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
bool table::setKeyNum(char num)
|
|
632
|
+
{
|
|
633
|
+
if ((m_keyNum != num) || ((m_keyNum >= 0)&& (m_table->file->inited == handler::NONE)))
|
|
634
|
+
{
|
|
635
|
+
m_table->file->ha_index_or_rnd_end();
|
|
636
|
+
|
|
637
|
+
if(keynumCheck(num))
|
|
638
|
+
{
|
|
639
|
+
m_keyNum = num;
|
|
640
|
+
m_table->file->ha_index_init(m_keyNum, 1/*sorted*/);
|
|
641
|
+
return true;
|
|
642
|
+
}
|
|
643
|
+
else
|
|
644
|
+
{
|
|
645
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return true;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
void table::fillNull(uchar* ptr, int size)
|
|
653
|
+
{
|
|
654
|
+
for (int i = 0;i < size;i++)
|
|
655
|
+
{
|
|
656
|
+
if (ptr[i] == 0)
|
|
657
|
+
{
|
|
658
|
+
memset(ptr + i, 0, size - i);
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
void table::setKeyValues(const uchar* ptr, int size)
|
|
665
|
+
{
|
|
666
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
667
|
+
memcpy(&m_keybuf[0], ptr, std::min(MAX_KEYLEN, size));
|
|
668
|
+
int pos = 0;
|
|
669
|
+
for (int j = 0; j < (int)key.user_defined_key_parts; j++)
|
|
670
|
+
{
|
|
671
|
+
KEY_PART_INFO& seg = key.key_part[j];
|
|
672
|
+
if (seg.field->type()==MYSQL_TYPE_STRING)
|
|
673
|
+
fillNull(&m_keybuf[pos], seg.field->pack_length());
|
|
674
|
+
pos+=seg.field->pack_length();
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
If null able field segment that need add null indicator byte befor segment.
|
|
680
|
+
Then key buffer length equal key length + null able segments.
|
|
681
|
+
|
|
682
|
+
The purpose of null key is non create index.
|
|
683
|
+
At read operation set not null(zero) to null indicator.
|
|
684
|
+
|
|
685
|
+
Size bytes of var and blob field is 2 byte fixed.
|
|
686
|
+
All most of key_part.length(segment lenght) is equal field.pack_length.
|
|
687
|
+
But blob and prefix index is not equal pack_length.
|
|
688
|
+
|
|
689
|
+
Client needs to make the right image except for null byte.
|
|
690
|
+
*/
|
|
691
|
+
void table::setKeyValuesPacked(const uchar* ptr, int size)
|
|
692
|
+
{
|
|
693
|
+
|
|
694
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
695
|
+
int to = 0;
|
|
696
|
+
const uchar* from = ptr;
|
|
697
|
+
uint key_length = key.key_length;
|
|
698
|
+
|
|
699
|
+
for (int j = 0; j < (int)key.user_defined_key_parts; j++)
|
|
700
|
+
{
|
|
701
|
+
KEY_PART_INFO& seg = key.key_part[j];
|
|
702
|
+
if (seg.null_bit)
|
|
703
|
+
{
|
|
704
|
+
m_keybuf[to++] = 0x00;
|
|
705
|
+
seg.field->set_notnull();
|
|
706
|
+
}
|
|
707
|
+
if (seg.null_bit && isNisField(seg.field->field_name))
|
|
708
|
+
{
|
|
709
|
+
m_keybuf[to++] = 0x00;
|
|
710
|
+
seg.field->set_notnull();
|
|
711
|
+
}
|
|
712
|
+
else
|
|
713
|
+
{
|
|
714
|
+
int copylen = seg.length;
|
|
715
|
+
if (seg.key_part_flag & HA_BLOB_PART || seg.key_part_flag & HA_VAR_LENGTH_PART)
|
|
716
|
+
copylen += 2;
|
|
717
|
+
memcpy(&m_keybuf[to], from, copylen);
|
|
718
|
+
to += copylen;
|
|
719
|
+
from += copylen;
|
|
720
|
+
|
|
721
|
+
if (to>=MAX_KEYLEN)
|
|
722
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_KEYBUFFERTOOSMALL, "");
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
uint table::keyPackCopy(uchar* ptr)
|
|
729
|
+
{
|
|
730
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
731
|
+
if ((key.flags & HA_NULL_PART_KEY) || (key.flags & HA_VAR_LENGTH_KEY))
|
|
732
|
+
{
|
|
733
|
+
int from = 0;
|
|
734
|
+
uchar* to = ptr;
|
|
735
|
+
uint key_length = key.key_length;
|
|
736
|
+
|
|
737
|
+
for (int j = 0; j < (int)key.user_defined_key_parts; j++)
|
|
738
|
+
{
|
|
739
|
+
KEY_PART_INFO& seg = key.key_part[j];
|
|
740
|
+
if (seg.null_bit)
|
|
741
|
+
from++;
|
|
742
|
+
if (seg.null_bit && isNisField(seg.field->field_name))
|
|
743
|
+
from++;
|
|
744
|
+
else
|
|
745
|
+
{
|
|
746
|
+
int copylen = seg.length;
|
|
747
|
+
if (seg.key_part_flag & HA_BLOB_PART || seg.key_part_flag & HA_VAR_LENGTH_PART)
|
|
748
|
+
copylen += 2;
|
|
749
|
+
memcpy(to, &m_keybuf[from], copylen);
|
|
750
|
+
to += copylen;
|
|
751
|
+
from += copylen;
|
|
752
|
+
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
return (uint)(to-ptr);
|
|
756
|
+
}
|
|
757
|
+
memcpy(ptr, keybuf(), keylen());
|
|
758
|
+
return keylen();
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
void* table::record()const
|
|
762
|
+
{
|
|
763
|
+
Field* fd = m_table->field[0];
|
|
764
|
+
return fd->ptr;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/** if offset and lastVarLenBytes() is non zero that is m_recordFormatType=RF_FIXED_PLUS_VALIABLE_LEN.
|
|
768
|
+
* ptr is excluding null flag sgement.
|
|
769
|
+
*/
|
|
770
|
+
void table::setRecord(void* ptr, unsigned short size, int offset)
|
|
771
|
+
{
|
|
772
|
+
m_cursor = false;
|
|
773
|
+
Field* fd = m_table->field[0];//remove null flag segment
|
|
774
|
+
if (offset + size <= (unsigned short)m_table->s->reclength + lastVarLenBytes())
|
|
775
|
+
{
|
|
776
|
+
if (size>0)
|
|
777
|
+
memcpy(fd->ptr + offset, ptr, size);
|
|
778
|
+
}
|
|
779
|
+
else
|
|
780
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_INVALID_DATASIZE, "");
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
inline bool isNull(Field* fd)
|
|
784
|
+
{
|
|
785
|
+
if (isVarType(fd->type()))
|
|
786
|
+
{
|
|
787
|
+
int len = *((unsigned char*)fd->ptr);
|
|
788
|
+
if (fd->field_length>255)
|
|
789
|
+
len = *((unsigned short*)fd->ptr);
|
|
790
|
+
|
|
791
|
+
return (len==0);
|
|
792
|
+
}
|
|
793
|
+
else
|
|
794
|
+
{
|
|
795
|
+
unsigned int k=0;
|
|
796
|
+
for (k=0;k<fd->key_length();k++)
|
|
797
|
+
if (fd->ptr[k]) break;
|
|
798
|
+
|
|
799
|
+
if (k==fd->key_length())
|
|
800
|
+
return true;
|
|
801
|
+
}
|
|
802
|
+
return false;
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
inline bool isNullNis(KEY& key, bool all)
|
|
806
|
+
{
|
|
807
|
+
for (int j=1;j<(int)key.user_defined_key_parts;j++)
|
|
808
|
+
{
|
|
809
|
+
Field* fd = key.key_part[j].field;
|
|
810
|
+
if (key.key_part[j].null_bit)
|
|
811
|
+
{
|
|
812
|
+
bool v = isNull(fd);
|
|
813
|
+
v ? fd->set_null():fd->set_notnull();
|
|
814
|
+
if (all && !v)
|
|
815
|
+
return false;
|
|
816
|
+
else if(!all && v)
|
|
817
|
+
return true;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
if (all)
|
|
821
|
+
return true;
|
|
822
|
+
return false;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
void table::setBlobFieldPointer(const bzs::db::blobHeader* hd)
|
|
826
|
+
{
|
|
827
|
+
|
|
828
|
+
if (hd)
|
|
829
|
+
{
|
|
830
|
+
assert(hd->curRow < hd->rows);
|
|
831
|
+
const blobField* f = hd->nextField;
|
|
832
|
+
for (int i=0;i<hd->fieldCount;i++)
|
|
833
|
+
{
|
|
834
|
+
Field* fd = m_table->field[f->fieldNum];
|
|
835
|
+
int sizeByte = blob_var_bytes(fd);
|
|
836
|
+
memcpy(fd->ptr, &f->size, sizeByte);
|
|
837
|
+
const char* data = f->data();
|
|
838
|
+
memcpy(fd->ptr+sizeByte, &data, sizeof(char*));
|
|
839
|
+
f = f->next();
|
|
840
|
+
}
|
|
841
|
+
++hd->curRow;
|
|
842
|
+
hd->nextField = (blobField*)f;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
/** A packed data set to the record buffer.
|
|
848
|
+
*/
|
|
849
|
+
void table::setRecordFromPacked(const uchar* packedPtr, uint size, const bzs::db::blobHeader* hd)
|
|
850
|
+
{
|
|
851
|
+
const uchar* p = packedPtr;
|
|
852
|
+
if (recordFormatType() & RF_FIXED_PLUS_VALIABLE_LEN)
|
|
853
|
+
{
|
|
854
|
+
int varlenbyte = lastVarLenBytes();
|
|
855
|
+
int varlenStartPos = lastVarFieldPos();
|
|
856
|
+
setRecord((void*)p, varlenStartPos);
|
|
857
|
+
int len = std::min((int)(size - varlenStartPos), (int)recordLenCl() - varlenStartPos);
|
|
858
|
+
if (len > 0)
|
|
859
|
+
{
|
|
860
|
+
setRecord(&len, varlenbyte, varlenStartPos);
|
|
861
|
+
//if (len > 0)
|
|
862
|
+
setRecord((void*)(p + varlenStartPos), len, varlenStartPos + varlenbyte);
|
|
863
|
+
}else if (len == 0)
|
|
864
|
+
;
|
|
865
|
+
else
|
|
866
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_BUFFERTOOSMALL, "copyDataTo");
|
|
867
|
+
}else if ((recordFormatType() & RF_VALIABLE_LEN)
|
|
868
|
+
|| (recordFormatType() & RF_INCLUDE_NIS))
|
|
869
|
+
{
|
|
870
|
+
//It copies for every field.
|
|
871
|
+
for (uint i=0;i<m_table->s->fields;i++)
|
|
872
|
+
{
|
|
873
|
+
Field* fd = m_table->field[i];
|
|
874
|
+
if (isNisField(fd->field_name))
|
|
875
|
+
fd->ptr[0] = 0x00;//The Nis field is not sent from a client.
|
|
876
|
+
else
|
|
877
|
+
{
|
|
878
|
+
int len = fd->pack_length();
|
|
879
|
+
if (isVarType(fd->type()))
|
|
880
|
+
len = var_total_len(p, var_bytes(fd));
|
|
881
|
+
|
|
882
|
+
memcpy(fd->ptr, p, len);
|
|
883
|
+
p += len;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
if (m_table->s->blob_fields)
|
|
887
|
+
setBlobFieldPointer(hd);
|
|
888
|
+
}
|
|
889
|
+
else
|
|
890
|
+
setRecord((void*)p, std::min(size, recordLenCl()));
|
|
891
|
+
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/** A record image is packed, and is copied to the specified buffer, and length is returned.
|
|
895
|
+
* -maxsize can be specified when recordFormatType() is RF_VALIABLE_LEN.
|
|
896
|
+
* -Length is not inspected if maxsize is zero.
|
|
897
|
+
* -When a buffer is too short, zero is returned to a result.
|
|
898
|
+
*/
|
|
899
|
+
uint table::recordPackCopy(char* buf, uint maxsize)
|
|
900
|
+
{
|
|
901
|
+
char* p = buf;
|
|
902
|
+
|
|
903
|
+
if ((recordFormatType() & RF_VALIABLE_LEN)
|
|
904
|
+
|| (recordFormatType() & RF_INCLUDE_NIS))
|
|
905
|
+
{
|
|
906
|
+
int blobs = 0;
|
|
907
|
+
for (uint i=0;i<m_table->s->fields;i++)
|
|
908
|
+
{
|
|
909
|
+
Field* fd = m_table->field[i];
|
|
910
|
+
if (isNisField(fd->field_name))
|
|
911
|
+
;//The Nis field is not sent to a client.
|
|
912
|
+
else
|
|
913
|
+
{
|
|
914
|
+
uint len = fd->pack_length();
|
|
915
|
+
if (isVarType(fd->type()))
|
|
916
|
+
len = var_total_len(fd);
|
|
917
|
+
if (maxsize && ((p - buf + len) > maxsize))
|
|
918
|
+
return 0;
|
|
919
|
+
memcpy(p, fd->ptr, len);
|
|
920
|
+
p+=len;
|
|
921
|
+
if (isBlobType(fd->type()))
|
|
922
|
+
{
|
|
923
|
+
++blobs;
|
|
924
|
+
addBlobBuffer(fd->field_index);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
setBlobFieldCount(blobs);
|
|
929
|
+
}else
|
|
930
|
+
{
|
|
931
|
+
uint varLenBytes = lastVarLenBytes();
|
|
932
|
+
uint varLenBytesPos = lastVarFieldPos();
|
|
933
|
+
const uchar* data = (const uchar *) record();
|
|
934
|
+
int len = recordLenCl();
|
|
935
|
+
if (varLenBytes)
|
|
936
|
+
{
|
|
937
|
+
memcpy(p, data, varLenBytesPos);
|
|
938
|
+
p += varLenBytesPos;
|
|
939
|
+
data += varLenBytesPos;
|
|
940
|
+
if (varLenBytes == 1)
|
|
941
|
+
len = *data;
|
|
942
|
+
else
|
|
943
|
+
len = *((const unsigned short*)data);
|
|
944
|
+
//In the variable length of tdap type, it returns except for varsize.
|
|
945
|
+
data += varLenBytes;
|
|
946
|
+
}
|
|
947
|
+
memcpy(p, data, len);
|
|
948
|
+
p += len;
|
|
949
|
+
}
|
|
950
|
+
return (uint)(p - buf);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
inline bool table::keynumCheck(char num)
|
|
954
|
+
{
|
|
955
|
+
return ((num>=0) && (num < (short)m_table->s->keys));
|
|
956
|
+
//||(num == m_table->s->primary_key));
|
|
957
|
+
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
inline void table::unlockRow()
|
|
961
|
+
{
|
|
962
|
+
if (!m_nounlock && m_validCursor && m_db.inTransaction() && (m_db.transactionType()== 0))
|
|
963
|
+
{
|
|
964
|
+
m_table->file->unlock_row();
|
|
965
|
+
m_nounlock = false;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
}
|
|
969
|
+
/* read by key
|
|
970
|
+
* A key field value is set in advance
|
|
971
|
+
*/
|
|
972
|
+
void table::seekKey(enum ha_rkey_function find_flag)
|
|
973
|
+
{
|
|
974
|
+
m_nonNcc = false;
|
|
975
|
+
if(keynumCheck(m_keyNum))
|
|
976
|
+
{
|
|
977
|
+
unlockRow();
|
|
978
|
+
m_stat = m_table->file->ha_index_read_map(m_table->record[0], &m_keybuf[0], keymap(), find_flag);
|
|
979
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
980
|
+
if (m_stat==0)
|
|
981
|
+
{
|
|
982
|
+
if (find_flag != HA_READ_KEY_EXACT)
|
|
983
|
+
key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
984
|
+
}
|
|
985
|
+
}else
|
|
986
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
987
|
+
if ((m_stat == HA_ERR_KEY_NOT_FOUND) && (find_flag != HA_READ_KEY_EXACT))
|
|
988
|
+
m_stat = HA_ERR_END_OF_FILE;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
void table::moveKey(boost::function<int()> func)
|
|
992
|
+
{
|
|
993
|
+
m_nonNcc = false;
|
|
994
|
+
if(keynumCheck(m_keyNum))
|
|
995
|
+
{
|
|
996
|
+
unlockRow();
|
|
997
|
+
|
|
998
|
+
m_stat = func();
|
|
999
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
1000
|
+
if (m_stat == 0)
|
|
1001
|
+
key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
1002
|
+
}else
|
|
1003
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
1004
|
+
if (m_stat == HA_ERR_KEY_NOT_FOUND)
|
|
1005
|
+
m_stat = HA_ERR_END_OF_FILE;
|
|
1006
|
+
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
void table::getNextSame()
|
|
1010
|
+
{
|
|
1011
|
+
m_nonNcc = false;
|
|
1012
|
+
if(keynumCheck(m_keyNum))
|
|
1013
|
+
{
|
|
1014
|
+
if (m_validCursor && m_db.inTransaction() && (m_db.transactionType()== 0))
|
|
1015
|
+
m_table->file->unlock_row();
|
|
1016
|
+
m_stat = m_table->file->ha_index_next_same(m_table->record[0], &m_keybuf[0], keymap());
|
|
1017
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
1018
|
+
if (m_stat==0)
|
|
1019
|
+
key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
1020
|
+
}else
|
|
1021
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
void table::getLast()
|
|
1025
|
+
{
|
|
1026
|
+
moveKey(boost::bind(&handler::ha_index_last, m_table->file, m_table->record[0]));
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
void table::getFirst()
|
|
1030
|
+
{
|
|
1031
|
+
moveKey(boost::bind(&handler::ha_index_first, m_table->file, m_table->record[0]));
|
|
1032
|
+
|
|
1033
|
+
#if (defined(DEBUG) && defined(WIN32))
|
|
1034
|
+
|
|
1035
|
+
char buf[1024];
|
|
1036
|
+
sprintf(buf, "name=%s reclength=%d rec_buff_length=%d\r\n",m_name.c_str(), m_table->s->reclength
|
|
1037
|
+
,m_table->s->rec_buff_length);
|
|
1038
|
+
OutputDebugString(buf);
|
|
1039
|
+
for (uint i=0;i<m_table->s->fields;i++)
|
|
1040
|
+
{
|
|
1041
|
+
Field* fd = m_table->s->field[i];
|
|
1042
|
+
|
|
1043
|
+
sprintf(buf, "\tpack_length=%d field_length=%d key_length=%d\r\n",fd->pack_length()
|
|
1044
|
+
, fd->field_length,fd->key_length());
|
|
1045
|
+
OutputDebugString(buf);
|
|
1046
|
+
}
|
|
1047
|
+
#endif
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
void table::getNext()
|
|
1051
|
+
{
|
|
1052
|
+
if (!m_cursor)
|
|
1053
|
+
{
|
|
1054
|
+
m_stat = HA_ERR_NO_ACTIVE_RECORD;
|
|
1055
|
+
return ;
|
|
1056
|
+
}
|
|
1057
|
+
if (m_nonNcc)
|
|
1058
|
+
{//It moves to the position after updating.
|
|
1059
|
+
//Since it may be lost, ref is compared and the next is decided.
|
|
1060
|
+
movePos(position(true), m_keyNum, true);
|
|
1061
|
+
if (m_stat) return ;
|
|
1062
|
+
}
|
|
1063
|
+
moveKey(boost::bind(&handler::ha_index_next, m_table->file, m_table->record[0]));
|
|
1064
|
+
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
void table::getPrev()
|
|
1068
|
+
{
|
|
1069
|
+
if (!m_cursor)
|
|
1070
|
+
{
|
|
1071
|
+
m_stat = HA_ERR_NO_ACTIVE_RECORD;
|
|
1072
|
+
return ;
|
|
1073
|
+
}
|
|
1074
|
+
if (m_nonNcc)
|
|
1075
|
+
{
|
|
1076
|
+
movePos(position(true), m_keyNum, true);
|
|
1077
|
+
if (m_stat) return ;
|
|
1078
|
+
}
|
|
1079
|
+
moveKey(boost::bind(&handler::ha_index_prev, m_table->file, m_table->record[0]));
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
bool table::keyCheckForPercent()
|
|
1083
|
+
{
|
|
1084
|
+
if (m_keyNum == -1)
|
|
1085
|
+
m_keyNum = m_table->s->primary_key;
|
|
1086
|
+
//The value of the beginning of a key
|
|
1087
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
1088
|
+
if (key.key_length > 128)
|
|
1089
|
+
return false;
|
|
1090
|
+
return true;
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
void table::preBuildPercent(uchar* first, uchar* last)
|
|
1094
|
+
{
|
|
1095
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
1096
|
+
getFirst();
|
|
1097
|
+
if (m_stat == 0)
|
|
1098
|
+
{
|
|
1099
|
+
key_copy(first, m_table->record[0], &key, KEYLEN_ALLCOPY);
|
|
1100
|
+
getLast();
|
|
1101
|
+
if (m_stat == 0)
|
|
1102
|
+
{
|
|
1103
|
+
key_copy(last, m_table->record[0], &key, KEYLEN_ALLCOPY);
|
|
1104
|
+
memset(m_keybuf.get(), 0, MAX_KEYLEN);
|
|
1105
|
+
}else
|
|
1106
|
+
THROW_BZS_ERROR_WITH_CODEMSG(m_stat, "connot seek last position.");
|
|
1107
|
+
}else
|
|
1108
|
+
THROW_BZS_ERROR_WITH_CODEMSG(m_stat, "connot seek first position.");
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
void table::getByPercentage(unsigned short per)
|
|
1112
|
+
{
|
|
1113
|
+
m_nonNcc = false;
|
|
1114
|
+
if (!keyCheckForPercent())
|
|
1115
|
+
{
|
|
1116
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
1117
|
+
return ;
|
|
1118
|
+
}
|
|
1119
|
+
if (per > 9800)
|
|
1120
|
+
{
|
|
1121
|
+
getLast();
|
|
1122
|
+
return;
|
|
1123
|
+
}else if(per < 200)
|
|
1124
|
+
{
|
|
1125
|
+
getFirst();
|
|
1126
|
+
return;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
uchar keybufFirst[MAX_KEYLEN]={0x00};
|
|
1130
|
+
uchar keybufLast[MAX_KEYLEN]={0x00};
|
|
1131
|
+
preBuildPercent(keybufFirst, keybufLast);
|
|
1132
|
+
if (m_stat == 0)
|
|
1133
|
+
{
|
|
1134
|
+
//5% of position is obtained.
|
|
1135
|
+
uchar* st = keybufFirst;
|
|
1136
|
+
uchar* en = keybufLast;
|
|
1137
|
+
uchar* cu = (uchar*) keybuf();
|
|
1138
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
1139
|
+
uint keylen = key.key_length + 10;
|
|
1140
|
+
boost::shared_array<uchar> stbuf(new uchar[keylen]);
|
|
1141
|
+
boost::shared_array<uchar> lsbuf(new uchar[keylen]);
|
|
1142
|
+
boost::shared_array<uchar> stbufResult(new uchar[keylen]);
|
|
1143
|
+
boost::shared_array<uchar> lsbufResult(new uchar[keylen]);
|
|
1144
|
+
percentageKey pk(key, st, en, cu);
|
|
1145
|
+
bool forwoard=true;
|
|
1146
|
+
int ov = 0;
|
|
1147
|
+
int sameCount = 0;
|
|
1148
|
+
while(1)
|
|
1149
|
+
{
|
|
1150
|
+
pk.reset(st, en, cu);
|
|
1151
|
+
int ret = pk.setKeyValueByPer(5000, forwoard);
|
|
1152
|
+
if (ret == KEY_ALL_SGMENTS_SAME)
|
|
1153
|
+
break;//THROW_BZS_ERROR_WITH_CODEMSG(1, "first and last record are same key value.");
|
|
1154
|
+
else if(ret == KEY_NEED_SGMENT_COPY)
|
|
1155
|
+
pk.copyFirstDeferentSegment();
|
|
1156
|
+
int v = percentage(keybufFirst, keybufLast, cu)-1000;
|
|
1157
|
+
(ov == v)?++sameCount:sameCount= 0;
|
|
1158
|
+
if (sameCount > 100)
|
|
1159
|
+
break;
|
|
1160
|
+
ov = v;
|
|
1161
|
+
if (v < -250)
|
|
1162
|
+
{
|
|
1163
|
+
memcpy(stbuf.get(), cu, keylen);
|
|
1164
|
+
st = stbuf.get();
|
|
1165
|
+
forwoard = true;
|
|
1166
|
+
}else if (v > 250)
|
|
1167
|
+
{
|
|
1168
|
+
memcpy(lsbuf.get(), cu, keylen);
|
|
1169
|
+
en = lsbuf.get();
|
|
1170
|
+
forwoard = false;
|
|
1171
|
+
}else
|
|
1172
|
+
break;
|
|
1173
|
+
}
|
|
1174
|
+
memcpy(stbufResult.get(), cu, keylen);
|
|
1175
|
+
if (per > 1000)
|
|
1176
|
+
{
|
|
1177
|
+
//95% of position is obtained.
|
|
1178
|
+
forwoard=true;
|
|
1179
|
+
memcpy(cu, keybufLast, keylen);
|
|
1180
|
+
memcpy(lsbuf.get(), keybufLast, keylen);
|
|
1181
|
+
en = lsbuf.get();
|
|
1182
|
+
while(1)
|
|
1183
|
+
{
|
|
1184
|
+
pk.reset(st, en, cu);
|
|
1185
|
+
int ret = pk.setKeyValueByPer(5000, forwoard);
|
|
1186
|
+
if (ret == KEY_ALL_SGMENTS_SAME)
|
|
1187
|
+
break;///THROW_BZS_ERROR_WITH_CODEMSG(1, "connot seek percant position.");
|
|
1188
|
+
else if(ret == KEY_NEED_SGMENT_COPY)
|
|
1189
|
+
pk.copyFirstDeferentSegment();
|
|
1190
|
+
int v = percentage(keybufFirst, keybufLast, cu)-9000;
|
|
1191
|
+
(ov == v)?++sameCount:sameCount= 0;
|
|
1192
|
+
if (sameCount > 100)
|
|
1193
|
+
break;
|
|
1194
|
+
ov = v;
|
|
1195
|
+
if (v < -250)
|
|
1196
|
+
{
|
|
1197
|
+
memcpy(stbuf.get(), cu, keylen);
|
|
1198
|
+
st = stbuf.get();
|
|
1199
|
+
forwoard = true;
|
|
1200
|
+
}else if (v > 250)
|
|
1201
|
+
{
|
|
1202
|
+
memcpy(lsbuf.get(), cu, keylen);
|
|
1203
|
+
en = lsbuf.get();
|
|
1204
|
+
forwoard = false;
|
|
1205
|
+
}else
|
|
1206
|
+
break;
|
|
1207
|
+
}
|
|
1208
|
+
memcpy(lsbufResult.get(), cu, keylen);
|
|
1209
|
+
pk.reset(stbufResult.get(), lsbufResult.get(), cu);
|
|
1210
|
+
|
|
1211
|
+
pk.setKeyValueByPer( per, true);
|
|
1212
|
+
}
|
|
1213
|
+
seekKey(HA_READ_KEY_OR_NEXT);
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
int table::percentage(uchar* first, uchar* last, uchar* cur)
|
|
1219
|
+
{
|
|
1220
|
+
m_table->file->init_table_handle_for_HANDLER() ;
|
|
1221
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
1222
|
+
// 1 cur to last
|
|
1223
|
+
key_range minkey;
|
|
1224
|
+
minkey.key = cur;
|
|
1225
|
+
minkey.length = key.key_length;
|
|
1226
|
+
minkey.keypart_map = keymap();
|
|
1227
|
+
minkey.flag = HA_READ_KEY_EXACT;
|
|
1228
|
+
key_range maxkey = minkey;
|
|
1229
|
+
maxkey.key = last;
|
|
1230
|
+
ha_rows rows1 = m_table->file->records_in_range(m_keyNum, &minkey, &maxkey);
|
|
1231
|
+
|
|
1232
|
+
//2 first to last
|
|
1233
|
+
maxkey.key = first;
|
|
1234
|
+
ha_rows rows2 = m_table->file->records_in_range(m_keyNum, &maxkey, &minkey);
|
|
1235
|
+
|
|
1236
|
+
//3 record count
|
|
1237
|
+
ha_rows total = recordCount(true);
|
|
1238
|
+
|
|
1239
|
+
//result
|
|
1240
|
+
int v1 =10000-(int)(rows1*(double)10000/total);
|
|
1241
|
+
|
|
1242
|
+
int v2 =(int)(rows2*(double)10000/total);
|
|
1243
|
+
if (abs(5000-v1) > abs(5000-v2))
|
|
1244
|
+
return v1;
|
|
1245
|
+
return v2;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
void table::calcPercentage()
|
|
1249
|
+
{
|
|
1250
|
+
if (!keyCheckForPercent())
|
|
1251
|
+
{
|
|
1252
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
m_percentResult = 0;
|
|
1256
|
+
//The present key value is copied.
|
|
1257
|
+
uchar keybufCur[MAX_KEYLEN]={0x00};
|
|
1258
|
+
key_copy(keybufCur, m_table->record[0], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
1259
|
+
|
|
1260
|
+
uchar keybufFirst[MAX_KEYLEN]={0x00};
|
|
1261
|
+
uchar keybufLast[MAX_KEYLEN]={0x00};
|
|
1262
|
+
preBuildPercent(keybufFirst, keybufLast);
|
|
1263
|
+
|
|
1264
|
+
if (m_stat == 0)
|
|
1265
|
+
{ //restore current
|
|
1266
|
+
setKeyValues(keybufCur, 128);
|
|
1267
|
+
seekKey(HA_READ_KEY_EXACT);
|
|
1268
|
+
if (m_stat == 0)
|
|
1269
|
+
m_percentResult = percentage(keybufFirst,keybufLast, keybufCur);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
void table::stepFirst()
|
|
1274
|
+
{
|
|
1275
|
+
if (m_table->s->primary_key < m_table->s->keys)
|
|
1276
|
+
{
|
|
1277
|
+
setKeyNum(m_table->s->primary_key);
|
|
1278
|
+
getFirst();
|
|
1279
|
+
}else
|
|
1280
|
+
{
|
|
1281
|
+
if (setNonKey(true))
|
|
1282
|
+
{
|
|
1283
|
+
m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
|
|
1284
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
1285
|
+
}
|
|
1286
|
+
else
|
|
1287
|
+
m_stat = STATUS_INVALID_KEYNUM;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
void table::stepLast()
|
|
1292
|
+
{
|
|
1293
|
+
if (m_table->s->primary_key < m_table->s->keys)
|
|
1294
|
+
{
|
|
1295
|
+
setKeyNum(m_table->s->primary_key);
|
|
1296
|
+
getLast();
|
|
1297
|
+
}else
|
|
1298
|
+
m_stat = STATUS_NOSUPPORT_OP;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
void table::stepNext()
|
|
1302
|
+
{
|
|
1303
|
+
m_nonNcc = false;
|
|
1304
|
+
if (m_table->s->primary_key < m_table->s->keys)
|
|
1305
|
+
{
|
|
1306
|
+
setKeyNum(m_table->s->primary_key);
|
|
1307
|
+
getNext();
|
|
1308
|
+
}else
|
|
1309
|
+
{
|
|
1310
|
+
if (m_keyNum != -2)
|
|
1311
|
+
{
|
|
1312
|
+
if (setNonKey(false))
|
|
1313
|
+
{
|
|
1314
|
+
m_stat = m_table->file->ha_rnd_pos(m_table->record[0], (uchar*)position(true));
|
|
1315
|
+
if (m_stat != 0)return;
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
|
|
1319
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
void table::stepPrev()
|
|
1324
|
+
{
|
|
1325
|
+
m_nonNcc = false;
|
|
1326
|
+
if (m_table->s->primary_key < m_table->s->keys)
|
|
1327
|
+
{
|
|
1328
|
+
setKeyNum(m_table->s->primary_key);
|
|
1329
|
+
getPrev();
|
|
1330
|
+
}
|
|
1331
|
+
else
|
|
1332
|
+
m_stat = STATUS_NOSUPPORT_OP;
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
void table::readRecords(IReadRecordsHandler* hdr, bool includeCurrent, int type)
|
|
1336
|
+
{
|
|
1337
|
+
if ((m_table->file->inited != handler::INDEX) || !m_cursor)
|
|
1338
|
+
{
|
|
1339
|
+
m_stat = STATUS_NO_CURRENT;
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
m_nonNcc = false;
|
|
1343
|
+
int reject = (hdr->rejectCount()==0)?4096:hdr->rejectCount();
|
|
1344
|
+
int rows = hdr->maxRows();
|
|
1345
|
+
|
|
1346
|
+
//Is a current position read or not?
|
|
1347
|
+
bool read = !includeCurrent;
|
|
1348
|
+
bool unlock = (!m_db.inSnapshot() && !m_db.inTransaction()) || (m_db.inTransaction() && (m_db.transactionType()== 0));
|
|
1349
|
+
while((reject!=0) && (rows!=0))
|
|
1350
|
+
{
|
|
1351
|
+
if (read)
|
|
1352
|
+
{
|
|
1353
|
+
|
|
1354
|
+
if (unlock && !m_nounlock && m_validCursor)
|
|
1355
|
+
{
|
|
1356
|
+
m_table->file->unlock_row();
|
|
1357
|
+
m_nounlock = false;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
if (type == READ_RECORD_GETNEXT)
|
|
1361
|
+
m_stat = m_table->file->ha_index_next(m_table->record[0]);
|
|
1362
|
+
else if (type == READ_RECORD_GETPREV)
|
|
1363
|
+
m_stat = m_table->file->ha_index_prev(m_table->record[0]);
|
|
1364
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
1365
|
+
}else
|
|
1366
|
+
read = true;
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
if (m_stat)
|
|
1370
|
+
break;
|
|
1371
|
+
int ret = hdr->match(type == READ_RECORD_GETNEXT);
|
|
1372
|
+
if (ret == REC_MACTH)
|
|
1373
|
+
{
|
|
1374
|
+
m_stat = hdr->write(position(), posPtrLen());
|
|
1375
|
+
if (m_stat) break;
|
|
1376
|
+
--rows;
|
|
1377
|
+
}
|
|
1378
|
+
else if (ret == REC_NOMACTH_NOMORE)
|
|
1379
|
+
{
|
|
1380
|
+
m_stat = STATUS_REACHED_FILTER_COND;
|
|
1381
|
+
return ;
|
|
1382
|
+
}
|
|
1383
|
+
else
|
|
1384
|
+
--reject;
|
|
1385
|
+
}
|
|
1386
|
+
//m_cursor = m_validCursor = (m_stat == 0);
|
|
1387
|
+
if (reject ==0)
|
|
1388
|
+
m_stat = STATUS_LIMMIT_OF_REJECT;
|
|
1389
|
+
|
|
1390
|
+
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
/* seek to pos by ref
|
|
1394
|
+
* need before set keybuf and keynum
|
|
1395
|
+
*/
|
|
1396
|
+
//private
|
|
1397
|
+
void table::seekPos(const uchar* rawPos)
|
|
1398
|
+
{
|
|
1399
|
+
seekKey(HA_READ_KEY_OR_NEXT);
|
|
1400
|
+
if (m_keyNum == m_table->s->primary_key)
|
|
1401
|
+
return;
|
|
1402
|
+
int cmp;
|
|
1403
|
+
while ((m_stat==0) && ((cmp = m_table->file->cmp_ref(position(true), rawPos))!=0))
|
|
1404
|
+
{
|
|
1405
|
+
unlockRow();
|
|
1406
|
+
m_table->file->ha_index_next_same(m_table->record[0], &m_keybuf[0], keymap());
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
void table::movePos(const uchar* pos, char keyNum, bool sureRawValue)
|
|
1411
|
+
{
|
|
1412
|
+
const uchar* rawPos = pos;
|
|
1413
|
+
if (!sureRawValue && (m_table->file->ref_length > REF_SIZE_MAX))
|
|
1414
|
+
rawPos = bms()->getRefByBm(*(unsigned int*)pos);
|
|
1415
|
+
|
|
1416
|
+
setNonKey();
|
|
1417
|
+
unlockRow();
|
|
1418
|
+
m_stat = m_table->file->ha_rnd_pos(m_table->record[0], (uchar*)rawPos);
|
|
1419
|
+
m_cursor = (m_stat == 0);
|
|
1420
|
+
if (keyNum==-1)
|
|
1421
|
+
return ;
|
|
1422
|
+
if (m_stat==0)
|
|
1423
|
+
{
|
|
1424
|
+
if (m_keyNum != keyNum)
|
|
1425
|
+
{// need key change
|
|
1426
|
+
key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[keyNum], KEYLEN_ALLCOPY);
|
|
1427
|
+
//It seek(s) until ref becomes the same, since it is a duplication key.
|
|
1428
|
+
setKeyNum(keyNum);
|
|
1429
|
+
seekPos(rawPos);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
bookmarks* table::bms()
|
|
1435
|
+
{
|
|
1436
|
+
if (m_bms==NULL)
|
|
1437
|
+
m_bms.reset(new bookmarks(m_table->file->ref_length));
|
|
1438
|
+
return m_bms.get();
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
/** get current record bookmark (position)
|
|
1442
|
+
*
|
|
1443
|
+
*/
|
|
1444
|
+
const uchar* table::position(bool raw)
|
|
1445
|
+
{
|
|
1446
|
+
m_table->file->position(m_table->record[0]);// handler is set uniqu number to ref.
|
|
1447
|
+
if (!raw && (m_table->file->ref_length > REF_SIZE_MAX))
|
|
1448
|
+
return bms()->getBookmarkPtr(m_table->file->ref);
|
|
1449
|
+
return m_table->file->ref;
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
uint table::posPtrLen()const
|
|
1453
|
+
{
|
|
1454
|
+
return std::min(m_table->file->ref_length, (uint)REF_SIZE_MAX) ;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
ha_rows table::recordCount(bool estimate)
|
|
1458
|
+
{
|
|
1459
|
+
if (estimate)
|
|
1460
|
+
{ //Since the answer of innodb is random, 1 returns also 0.
|
|
1461
|
+
//Since it is important, in the case of 1
|
|
1462
|
+
//, whether there is nothing or it is scan and investigate.
|
|
1463
|
+
m_table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
|
1464
|
+
ha_rows rows = m_table->file->records();
|
|
1465
|
+
if (rows>1)
|
|
1466
|
+
return rows;
|
|
1467
|
+
}
|
|
1468
|
+
uint n = 0;
|
|
1469
|
+
m_table->read_set= &m_table->tmp_set;
|
|
1470
|
+
bitmap_clear_all(m_table->read_set);
|
|
1471
|
+
setNonKey(true/*scan*/);
|
|
1472
|
+
m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
|
|
1473
|
+
while (m_stat == 0)
|
|
1474
|
+
{
|
|
1475
|
+
n++;
|
|
1476
|
+
m_stat = m_table->file->ha_rnd_next(m_table->record[0]);
|
|
1477
|
+
}
|
|
1478
|
+
m_table->read_set = &m_table->s->all_set;
|
|
1479
|
+
return n;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
void table::clearBuffer()
|
|
1483
|
+
{
|
|
1484
|
+
unsigned char* p = m_table->record[0];
|
|
1485
|
+
empty_record(m_table);
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
bool table::isNisKey(char num) const
|
|
1489
|
+
{
|
|
1490
|
+
if((num>=0) && (num < (short)m_table->s->keys))
|
|
1491
|
+
{
|
|
1492
|
+
Field* fd = m_table->key_info[num].key_part[0].field; //Nis is only in a head segment.
|
|
1493
|
+
if (isNisField(fd->field_name))
|
|
1494
|
+
return true;
|
|
1495
|
+
else if((fd->pack_length() == 1) && (fd->type() == MYSQL_TYPE_TINY) && fd->null_bit)
|
|
1496
|
+
return true;
|
|
1497
|
+
}
|
|
1498
|
+
return false;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
bool setNullIf(KEY& key)
|
|
1502
|
+
{
|
|
1503
|
+
bool nullkey = false;
|
|
1504
|
+
Field* fd = key.key_part[0].field; //Nis is only in a head segment.
|
|
1505
|
+
if (isNisField(fd->field_name))
|
|
1506
|
+
{
|
|
1507
|
+
if(isNullNis(key, fd->field_name[3]=='a'))
|
|
1508
|
+
{
|
|
1509
|
+
fd->set_null();
|
|
1510
|
+
nullkey = true;
|
|
1511
|
+
}
|
|
1512
|
+
else
|
|
1513
|
+
fd->set_notnull();
|
|
1514
|
+
}
|
|
1515
|
+
else
|
|
1516
|
+
{
|
|
1517
|
+
for (int j=0;j<(int)key.user_defined_key_parts;j++)
|
|
1518
|
+
{
|
|
1519
|
+
fd = key.key_part[j].field;
|
|
1520
|
+
if (key.key_part[j].null_bit && fd->ptr)
|
|
1521
|
+
{
|
|
1522
|
+
if (isNull(fd))
|
|
1523
|
+
{
|
|
1524
|
+
fd->set_null();
|
|
1525
|
+
nullkey = true;
|
|
1526
|
+
}else
|
|
1527
|
+
fd->set_notnull();
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
return nullkey;
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
/** Sets null value for all null able key fields
|
|
1535
|
+
* @return null sets field count
|
|
1536
|
+
*/
|
|
1537
|
+
int table::setKeyNullFlags()
|
|
1538
|
+
{
|
|
1539
|
+
int setCount = 0;
|
|
1540
|
+
if (m_table->s->null_fields)
|
|
1541
|
+
{
|
|
1542
|
+
for (int i=0;i<(int)m_table->s->keys;i++)
|
|
1543
|
+
{
|
|
1544
|
+
KEY& key = m_table->key_info[i];
|
|
1545
|
+
if (key.flags & HA_NULL_PART_KEY)
|
|
1546
|
+
{
|
|
1547
|
+
bool nullKey = setNullIf(key);
|
|
1548
|
+
if (nullKey && (i == m_keyNum))
|
|
1549
|
+
++setCount;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
return setCount;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
/** Sets null value for all null able fields
|
|
1557
|
+
*/
|
|
1558
|
+
void table::setFiledNullFlags()
|
|
1559
|
+
{
|
|
1560
|
+
std::vector<Field*>::iterator it = m_nonKeySegNullFields.begin();
|
|
1561
|
+
while (it != m_nonKeySegNullFields.end())
|
|
1562
|
+
{
|
|
1563
|
+
if (isNull(*it))
|
|
1564
|
+
(*it)->set_null();
|
|
1565
|
+
else
|
|
1566
|
+
(*it)->set_notnull();
|
|
1567
|
+
++it;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
__int64 table::insert(bool ncc)
|
|
1572
|
+
{
|
|
1573
|
+
if (!cp_is_write_lock(m_table->file))
|
|
1574
|
+
{
|
|
1575
|
+
m_stat = STATUS_INVALID_LOCKTYPE;
|
|
1576
|
+
return 0;
|
|
1577
|
+
}
|
|
1578
|
+
__int64 autoincValue = 0;
|
|
1579
|
+
|
|
1580
|
+
{
|
|
1581
|
+
autoincSetup setup(m_table);
|
|
1582
|
+
if (!ncc)
|
|
1583
|
+
key_copy(&m_nonNccKeybuf[0], m_table->record[1], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
1584
|
+
setKeyNullFlags();
|
|
1585
|
+
setFiledNullFlags();
|
|
1586
|
+
|
|
1587
|
+
m_stat = m_table->file->ha_write_row(m_table->record[0]);
|
|
1588
|
+
autoincValue = m_table->file->insert_id_for_cur_row;
|
|
1589
|
+
|
|
1590
|
+
if (m_stat==0 && m_table->file->insert_id_for_cur_row)
|
|
1591
|
+
{
|
|
1592
|
+
if (!m_bulkInserting)
|
|
1593
|
+
m_table->file->ha_release_auto_increment();
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
if (m_stat==0)
|
|
1598
|
+
{
|
|
1599
|
+
if (!ncc)//innodb default is ncc=-1.
|
|
1600
|
+
m_nonNcc = true;
|
|
1601
|
+
else if (!m_bulkInserting)
|
|
1602
|
+
key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
1603
|
+
m_cursor = m_validCursor = m_nounlock = (m_stat == 0);
|
|
1604
|
+
|
|
1605
|
+
m_changed = true;
|
|
1606
|
+
}
|
|
1607
|
+
return autoincValue;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
void table::beginUpdate(char keyNum)
|
|
1611
|
+
{
|
|
1612
|
+
m_table->file->try_semi_consistent_read(1);
|
|
1613
|
+
beginDel();
|
|
1614
|
+
if (m_stat==0)
|
|
1615
|
+
{
|
|
1616
|
+
if (keyNum >= 0)
|
|
1617
|
+
{
|
|
1618
|
+
key_copy(&m_nonNccKeybuf[0], m_table->record[0], &m_table->key_info[keyNum], KEYLEN_ALLCOPY);
|
|
1619
|
+
setKeyNum(keyNum);
|
|
1620
|
+
}
|
|
1621
|
+
store_record(m_table, record[1]);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
void table::beginDel()
|
|
1626
|
+
{
|
|
1627
|
+
if (m_cursor)
|
|
1628
|
+
{
|
|
1629
|
+
m_stat = 0;
|
|
1630
|
+
/* The current position is established in advance.
|
|
1631
|
+
If not in transaction then m_validCursor=false */
|
|
1632
|
+
if (m_validCursor == false)
|
|
1633
|
+
{
|
|
1634
|
+
store_record(m_table, record[1]);
|
|
1635
|
+
if (m_keyNum>=0)
|
|
1636
|
+
{
|
|
1637
|
+
//seek until ref is same.
|
|
1638
|
+
uchar rawPos[128];
|
|
1639
|
+
memcpy(rawPos, position(true), m_table->file->ref_length);
|
|
1640
|
+
seekPos(rawPos);
|
|
1641
|
+
}
|
|
1642
|
+
else
|
|
1643
|
+
movePos(position(true), -1, true);
|
|
1644
|
+
if (cmp_record(m_table, record[1]))
|
|
1645
|
+
m_stat = STATUS_CHANGE_CONFLICT;
|
|
1646
|
+
|
|
1647
|
+
m_cursor = m_validCursor = (m_stat == 0);
|
|
1648
|
+
if (m_stat)
|
|
1649
|
+
return ;
|
|
1650
|
+
}
|
|
1651
|
+
|
|
1652
|
+
}else
|
|
1653
|
+
m_stat = STATUS_NO_CURRENT;
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
/** Update current record.
|
|
1657
|
+
* It is indispensable that there is a current record in advance
|
|
1658
|
+
* and beginUpdate() is called.
|
|
1659
|
+
*/
|
|
1660
|
+
void table::update(bool ncc)
|
|
1661
|
+
{
|
|
1662
|
+
if (m_stat == 0)
|
|
1663
|
+
{
|
|
1664
|
+
|
|
1665
|
+
int nullFieldsOfCurrentKey = setKeyNullFlags();
|
|
1666
|
+
setFiledNullFlags();
|
|
1667
|
+
m_stat = m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
|
|
1668
|
+
if (m_stat==0 || (m_stat==HA_ERR_RECORD_IS_THE_SAME))
|
|
1669
|
+
{
|
|
1670
|
+
m_stat = 0;
|
|
1671
|
+
m_nonNcc = false;
|
|
1672
|
+
if (!ncc)//innodb default is ncc=-1.
|
|
1673
|
+
{
|
|
1674
|
+
//Only when the present key value is changed
|
|
1675
|
+
if (m_keyNum>=0)
|
|
1676
|
+
{
|
|
1677
|
+
const KEY& key = m_table->key_info[m_keyNum];
|
|
1678
|
+
key_copy(&m_keybuf[0], m_table->record[0], (KEY*)&key, KEYLEN_ALLCOPY);
|
|
1679
|
+
if (memcmp(&m_nonNccKeybuf[0], &m_keybuf[0], key.key_length))
|
|
1680
|
+
{
|
|
1681
|
+
//Since the NULL key was set, a current position is lost.
|
|
1682
|
+
if (nullFieldsOfCurrentKey==0)
|
|
1683
|
+
m_nonNcc = true;
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
m_cursor = m_validCursor = m_nounlock = (m_stat == 0);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
if (m_stat==0)
|
|
1691
|
+
m_changed = true;
|
|
1692
|
+
m_table->file->try_semi_consistent_read(0);
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
/** del current record.
|
|
1696
|
+
* It is indispensable that there is a current record in advance
|
|
1697
|
+
* and beginDel() is called.
|
|
1698
|
+
*/
|
|
1699
|
+
void table::del()
|
|
1700
|
+
{
|
|
1701
|
+
if (m_stat == 0)
|
|
1702
|
+
m_stat = m_table->file->ha_delete_row(m_table->record[0]);
|
|
1703
|
+
if (m_stat==0)
|
|
1704
|
+
m_changed = true;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
/** The offset position of the last VAR field data
|
|
1708
|
+
*/
|
|
1709
|
+
unsigned short table::lastVarFieldPos()const
|
|
1710
|
+
{
|
|
1711
|
+
if (m_table->s->varchar_fields && (m_recordFormatType == RF_FIXED_PLUS_VALIABLE_LEN))
|
|
1712
|
+
return (unsigned short)(lastVarFiled()->ptr - m_table->s->field[0]->ptr);
|
|
1713
|
+
return 0;
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
/** The data length of the field
|
|
1717
|
+
*/
|
|
1718
|
+
unsigned short table::fieldDataLen(int fieldNum) const
|
|
1719
|
+
{
|
|
1720
|
+
Field* fd = m_table->field[fieldNum];
|
|
1721
|
+
if (isVarType(fd->type()))
|
|
1722
|
+
return var_strlen(fd);
|
|
1723
|
+
return fd->pack_length();
|
|
1724
|
+
}
|
|
1725
|
+
|
|
1726
|
+
const char* table::keyName(char keyNum)
|
|
1727
|
+
{
|
|
1728
|
+
if((keyNum>=0) && (keyNum < (short)m_table->s->keys))
|
|
1729
|
+
{
|
|
1730
|
+
KEY& key = m_table->key_info[keyNum];
|
|
1731
|
+
return key.name;
|
|
1732
|
+
}
|
|
1733
|
+
return "";
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
int table::keynumByName(const char* name)const
|
|
1737
|
+
{
|
|
1738
|
+
if (*name==0x00)
|
|
1739
|
+
name = "PRIMARY";
|
|
1740
|
+
for (int i=0; i<(int)m_table->s->keys; i++)
|
|
1741
|
+
{
|
|
1742
|
+
if (strcmp(m_table->key_info[i].name, name) == 0)
|
|
1743
|
+
return i;
|
|
1744
|
+
}
|
|
1745
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_INVALID_KEYNAME, name);
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
void table::startBulkInsert(ha_rows rows)
|
|
1749
|
+
{
|
|
1750
|
+
m_table->file->ha_start_bulk_insert(rows);
|
|
1751
|
+
m_bulkInserting = true;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
void table::endBulkInsert()
|
|
1755
|
+
{
|
|
1756
|
+
if (m_bulkInserting)
|
|
1757
|
+
{
|
|
1758
|
+
key_copy(&m_keybuf[0], m_table->record[0], &m_table->key_info[m_keyNum], KEYLEN_ALLCOPY);
|
|
1759
|
+
m_bulkInserting = false;
|
|
1760
|
+
m_table->file->ha_release_auto_increment();
|
|
1761
|
+
m_table->file->ha_end_bulk_insert();
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
const char* table::valStr(int filedNum, int &size)
|
|
1766
|
+
{
|
|
1767
|
+
assert((filedNum>=0) && (filedNum < (int)m_table->s->fields));
|
|
1768
|
+
|
|
1769
|
+
Field* fd = m_table->field[filedNum];
|
|
1770
|
+
size = -1;
|
|
1771
|
+
if (fd->is_null())
|
|
1772
|
+
return "";
|
|
1773
|
+
else
|
|
1774
|
+
fd->val_str(&m_str, &m_str);
|
|
1775
|
+
size = m_str.length();
|
|
1776
|
+
return m_str.c_ptr();
|
|
1777
|
+
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
uint table::makeBlobFieldList(int fieldNum)
|
|
1781
|
+
{
|
|
1782
|
+
m_blobBuffer->clear();
|
|
1783
|
+
int st = fieldNum==-1?0:fieldNum;
|
|
1784
|
+
int en = fieldNum==-1?m_table->s->fields:fieldNum+1;
|
|
1785
|
+
uint count = 0;
|
|
1786
|
+
for (int i=st;i<en;i++)
|
|
1787
|
+
{
|
|
1788
|
+
Field* fd = m_table->field[fieldNum];
|
|
1789
|
+
if (isBlobType(fd->type()))
|
|
1790
|
+
{
|
|
1791
|
+
m_blobBuffer->addBlob(blob_len(fd), fd->field_index, fd->ptr + blob_var_bytes(fd));
|
|
1792
|
+
count++;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
m_blobBuffer->setFieldCount(count);
|
|
1796
|
+
return count;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
#ifdef USE_HANDLERSOCKET
|
|
1800
|
+
int table::fieldIndexByName(const char* name)const
|
|
1801
|
+
{
|
|
1802
|
+
int index = 0;
|
|
1803
|
+
for (Field** fd=m_table->field ; *fd; ++fd)
|
|
1804
|
+
{
|
|
1805
|
+
if (strcmp(name, (*fd)->field_name)==0)
|
|
1806
|
+
return index;
|
|
1807
|
+
++index;
|
|
1808
|
+
}
|
|
1809
|
+
THROW_BZS_ERROR_WITH_CODEMSG(STATUS_INVALID_FIELDNAME, name);
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
void table::setUseFieldList(const std::string& csv)
|
|
1813
|
+
{
|
|
1814
|
+
std::vector< std::string> values ;
|
|
1815
|
+
split(values, csv, ",");
|
|
1816
|
+
for (int i=0;i<values.size();i++)
|
|
1817
|
+
addUseField(fieldIndexByName(values[i].c_str()));
|
|
1818
|
+
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
inline void setSegmentValue(const KEY_PART_INFO& segment, const std::string& v)
|
|
1822
|
+
{
|
|
1823
|
+
segment.field->set_notnull();
|
|
1824
|
+
if (!((v.size() == 1) && (v[0] == 0x00)))
|
|
1825
|
+
segment.field->store(v.c_str(), (uint)v.size(), &my_charset_bin);
|
|
1826
|
+
else
|
|
1827
|
+
segment.field->set_null();
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
void table::setKeyValues(const std::vector<std::string>& values, int keypart, const std::string* inValue)
|
|
1831
|
+
{
|
|
1832
|
+
KEY& key = m_table->key_info[m_keyNum];
|
|
1833
|
+
for (int i=0;i<(int)key.user_defined_key_parts;i++)
|
|
1834
|
+
if (i < values.size())
|
|
1835
|
+
setSegmentValue(key.key_part[i], values[i]);
|
|
1836
|
+
if (keypart !=-1)
|
|
1837
|
+
setSegmentValue(key.key_part[keypart], *inValue);
|
|
1838
|
+
key_copy(&m_keybuf[0], m_table->record[0], &key, KEYLEN_ALLCOPY);
|
|
1839
|
+
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
void table::setValue(int index, const std::string& v, int type)
|
|
1843
|
+
{
|
|
1844
|
+
Field* field = *(m_table->field+index);
|
|
1845
|
+
if ((v.size() == 1) && (v[0] == 0x00))
|
|
1846
|
+
field->set_null();
|
|
1847
|
+
else
|
|
1848
|
+
field->set_notnull();
|
|
1849
|
+
if ((type == UPDATE_INC) || (type == UPDATE_DEC))
|
|
1850
|
+
{
|
|
1851
|
+
__int64 old = field->val_int();
|
|
1852
|
+
__int64 intv = _atoi64(v.c_str());
|
|
1853
|
+
if (type == UPDATE_INC)
|
|
1854
|
+
field->store(old + intv , false);
|
|
1855
|
+
else
|
|
1856
|
+
field->store(old - intv , false);
|
|
1857
|
+
}else
|
|
1858
|
+
field->store(v.c_str(), (uint)v.size(), &my_charset_bin);
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
void table::setUseValues(const std::vector<std::string>& values, int type)
|
|
1862
|
+
{
|
|
1863
|
+
for (int i=0;i<values.size();i++)
|
|
1864
|
+
{
|
|
1865
|
+
if (useFields().size()>i)
|
|
1866
|
+
setValue(m_useFields[i], values[i], type);
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
void table::checkFiledIndex(int index)
|
|
1871
|
+
{
|
|
1872
|
+
assert(index>=0);
|
|
1873
|
+
}
|
|
1874
|
+
|
|
1875
|
+
#endif //USE_HANDLERSOCKET
|
|
1876
|
+
|
|
1877
|
+
}//namespace mysql
|
|
1878
|
+
}//namespace engine
|
|
1879
|
+
}//namespace db
|
|
1880
|
+
}//namespace bzs
|
|
1881
|
+
|
|
1882
|
+
|