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.
Files changed (218) hide show
  1. checksums.yaml +7 -0
  2. data/BUILD_UNIX-JA +174 -0
  3. data/BUILD_WIN-JA +256 -0
  4. data/CMakeLists.txt +96 -0
  5. data/COPYING +339 -0
  6. data/README +406 -0
  7. data/README-JA +424 -0
  8. data/bin/common/tdclc_32_1_0.dll +0 -0
  9. data/bin/common/tdclc_64_1_0.dll +0 -0
  10. data/build/common/check_for_link_iconv.cmake +73 -0
  11. data/build/common/copyifgreater.cmd +30 -0
  12. data/build/common/copyifgreater.js +290 -0
  13. data/build/common/get_boost_libs.cmake +106 -0
  14. data/build/common/get_ruby_path.cmake +115 -0
  15. data/build/common/options.cmake +127 -0
  16. data/build/common/smart_install.cmake +263 -0
  17. data/build/common/system.cmake +122 -0
  18. data/build/common/transactd.rc.in +52 -0
  19. data/build/common/transactd_cl_common.cmake +101 -0
  20. data/build/common/transactd_cl_output.cmake +93 -0
  21. data/build/common/transactd_common.cmake +237 -0
  22. data/build/common/transactd_required.cmake +28 -0
  23. data/build/swig/ruby/generate.cmake.in +35 -0
  24. data/build/swig/ruby/generate.cmd.in +19 -0
  25. data/build/swig/ruby/ruby.swg +101 -0
  26. data/build/swig/tdcl.i +188 -0
  27. data/build/tdclc/BUILDNUMBER.txt +1 -0
  28. data/build/tdclc/CMakeLists.txt +170 -0
  29. data/build/tdclc/tdclc_32.cbproj +181 -0
  30. data/build/tdclc/tdclc_64.cbproj +205 -0
  31. data/build/tdclcpp/BUILDNUMBER.txt +1 -0
  32. data/build/tdclcpp/CMakeLists.txt +142 -0
  33. data/build/tdclcpp/tdclcpp_bcb_32.cbproj +239 -0
  34. data/build/tdclcpp/tdclcpp_bcb_64.cbproj +304 -0
  35. data/build/tdclrb/BUILDNUMBER.txt +1 -0
  36. data/build/tdclrb/CMakeLists.txt +258 -0
  37. data/build/tdclrb/GEM_VERSION +3 -0
  38. data/build/tdclrb/bldgem/extconf.rb +123 -0
  39. data/build/tdclrb/gem/INSTALLLOG.win32 +9 -0
  40. data/build/tdclrb/gem/Makefile.win32-VS +65 -0
  41. data/build/tdclrb/gem/Makefile.win32-prebuilt +48 -0
  42. data/build/tdclrb/gem/detect.rb +31 -0
  43. data/build/tdclrb/gem/helper.rb +113 -0
  44. data/build/tdclrb/gem/transactd.rb +22 -0
  45. data/build/tdclrb/gem_output.cmake +44 -0
  46. data/source/bzs/db/IBlobBuffer.h +51 -0
  47. data/source/bzs/db/blobBuffer.h +177 -0
  48. data/source/bzs/db/blobStructs.h +85 -0
  49. data/source/bzs/db/engine/mysql/IReadRecords.h +52 -0
  50. data/source/bzs/db/engine/mysql/bookmark.h +195 -0
  51. data/source/bzs/db/engine/mysql/database.cpp +1882 -0
  52. data/source/bzs/db/engine/mysql/database.h +465 -0
  53. data/source/bzs/db/engine/mysql/dbManager.cpp +303 -0
  54. data/source/bzs/db/engine/mysql/dbManager.h +143 -0
  55. data/source/bzs/db/engine/mysql/errorMessage.cpp +75 -0
  56. data/source/bzs/db/engine/mysql/errorMessage.h +43 -0
  57. data/source/bzs/db/engine/mysql/fieldAccess.h +158 -0
  58. data/source/bzs/db/engine/mysql/mydebuglog.cpp +349 -0
  59. data/source/bzs/db/engine/mysql/mydebuglog.h +89 -0
  60. data/source/bzs/db/engine/mysql/mysqlInternal.h +171 -0
  61. data/source/bzs/db/engine/mysql/mysqlThd.cpp +169 -0
  62. data/source/bzs/db/engine/mysql/mysqlThd.h +35 -0
  63. data/source/bzs/db/engine/mysql/percentageKey.h +260 -0
  64. data/source/bzs/db/protocol/ICommandExecuter.h +49 -0
  65. data/source/bzs/db/protocol/hs/hsCommandExecuter.cpp +689 -0
  66. data/source/bzs/db/protocol/hs/hsCommandExecuter.h +228 -0
  67. data/source/bzs/db/protocol/tdap/btrDate.cpp +437 -0
  68. data/source/bzs/db/protocol/tdap/btrDate.h +227 -0
  69. data/source/bzs/db/protocol/tdap/client/bulkInsert.h +127 -0
  70. data/source/bzs/db/protocol/tdap/client/client.cpp +106 -0
  71. data/source/bzs/db/protocol/tdap/client/client.h +292 -0
  72. data/source/bzs/db/protocol/tdap/client/connMgr.cpp +144 -0
  73. data/source/bzs/db/protocol/tdap/client/connMgr.h +82 -0
  74. data/source/bzs/db/protocol/tdap/client/database.cpp +863 -0
  75. data/source/bzs/db/protocol/tdap/client/database.h +118 -0
  76. data/source/bzs/db/protocol/tdap/client/databaseFactory.cpp +100 -0
  77. data/source/bzs/db/protocol/tdap/client/dbDef.cpp +1640 -0
  78. data/source/bzs/db/protocol/tdap/client/dbDef.h +135 -0
  79. data/source/bzs/db/protocol/tdap/client/dllmain.cpp +434 -0
  80. data/source/bzs/db/protocol/tdap/client/errorMessage.cpp +92 -0
  81. data/source/bzs/db/protocol/tdap/client/errorMessage_ja.cpp +98 -0
  82. data/source/bzs/db/protocol/tdap/client/fieldDDF.cpp +174 -0
  83. data/source/bzs/db/protocol/tdap/client/fieldDDF.h +91 -0
  84. data/source/bzs/db/protocol/tdap/client/fileDDF.cpp +140 -0
  85. data/source/bzs/db/protocol/tdap/client/fileDDF.h +86 -0
  86. data/source/bzs/db/protocol/tdap/client/filter.cpp +527 -0
  87. data/source/bzs/db/protocol/tdap/client/filter.h +154 -0
  88. data/source/bzs/db/protocol/tdap/client/indexDDF.cpp +137 -0
  89. data/source/bzs/db/protocol/tdap/client/indexDDF.h +84 -0
  90. data/source/bzs/db/protocol/tdap/client/nsDatabase.cpp +724 -0
  91. data/source/bzs/db/protocol/tdap/client/nsDatabase.h +123 -0
  92. data/source/bzs/db/protocol/tdap/client/nsTable.cpp +899 -0
  93. data/source/bzs/db/protocol/tdap/client/nsTable.h +199 -0
  94. data/source/bzs/db/protocol/tdap/client/request.h +198 -0
  95. data/source/bzs/db/protocol/tdap/client/sharedData.cpp +58 -0
  96. data/source/bzs/db/protocol/tdap/client/sharedData.h +56 -0
  97. data/source/bzs/db/protocol/tdap/client/sqlBuilder.cpp +574 -0
  98. data/source/bzs/db/protocol/tdap/client/sqlBuilder.h +53 -0
  99. data/source/bzs/db/protocol/tdap/client/stringConverter.h +627 -0
  100. data/source/bzs/db/protocol/tdap/client/table.cpp +2613 -0
  101. data/source/bzs/db/protocol/tdap/client/table.h +221 -0
  102. data/source/bzs/db/protocol/tdap/client/trdboostapi.h +1096 -0
  103. data/source/bzs/db/protocol/tdap/client/trdboostapiInternal.h +179 -0
  104. data/source/bzs/db/protocol/tdap/client/trdclcppautolink.h +40 -0
  105. data/source/bzs/db/protocol/tdap/client/trnsctcl.def +11 -0
  106. data/source/bzs/db/protocol/tdap/myDateTime.cpp +500 -0
  107. data/source/bzs/db/protocol/tdap/mysql/characterset.cpp +184 -0
  108. data/source/bzs/db/protocol/tdap/mysql/characterset.h +60 -0
  109. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.cpp +284 -0
  110. data/source/bzs/db/protocol/tdap/mysql/databaseSchema.h +53 -0
  111. data/source/bzs/db/protocol/tdap/mysql/debuglog.cpp +383 -0
  112. data/source/bzs/db/protocol/tdap/mysql/debuglog.h +106 -0
  113. data/source/bzs/db/protocol/tdap/mysql/recordsetReader.h +680 -0
  114. data/source/bzs/db/protocol/tdap/mysql/request.h +202 -0
  115. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.cpp +1020 -0
  116. data/source/bzs/db/protocol/tdap/mysql/tdapCommandExecuter.h +141 -0
  117. data/source/bzs/db/protocol/tdap/tdapRequest.h +190 -0
  118. data/source/bzs/db/protocol/tdap/tdapSchema.cpp +295 -0
  119. data/source/bzs/db/protocol/tdap/tdapSchema.h +558 -0
  120. data/source/bzs/db/protocol/tdap/tdapcapi.h +423 -0
  121. data/source/bzs/db/transactd/appBuilderImple.h +55 -0
  122. data/source/bzs/db/transactd/appModule.cpp +183 -0
  123. data/source/bzs/db/transactd/appModule.h +80 -0
  124. data/source/bzs/db/transactd/connManager.cpp +201 -0
  125. data/source/bzs/db/transactd/connManager.h +60 -0
  126. data/source/bzs/db/transactd/connectionRecord.h +69 -0
  127. data/source/bzs/db/transactd/transactd.cpp +325 -0
  128. data/source/bzs/env/compiler.h +135 -0
  129. data/source/bzs/env/crosscompile.cpp +130 -0
  130. data/source/bzs/env/crosscompile.h +150 -0
  131. data/source/bzs/env/fileopen.h +36 -0
  132. data/source/bzs/env/mbcswchrLinux.cpp +40 -0
  133. data/source/bzs/env/mbcswchrLinux.h +88 -0
  134. data/source/bzs/env/tstring.h +183 -0
  135. data/source/bzs/example/changeSchema.cpp +117 -0
  136. data/source/bzs/example/changeSchema_c.cpp +78 -0
  137. data/source/bzs/example/connection_pool_c.cpp +171 -0
  138. data/source/bzs/example/createDatabase.cpp +305 -0
  139. data/source/bzs/example/createDatabase_c.cpp +202 -0
  140. data/source/bzs/example/deleteRecords.cpp +87 -0
  141. data/source/bzs/example/deleteRecords_c.cpp +57 -0
  142. data/source/bzs/example/dropDatabase.cpp +59 -0
  143. data/source/bzs/example/dropDatabase_c.cpp +34 -0
  144. data/source/bzs/example/insertRecords.cpp +212 -0
  145. data/source/bzs/example/insertRecords_c.cpp +153 -0
  146. data/source/bzs/example/readRecords.cpp +141 -0
  147. data/source/bzs/example/readRecords_c.cpp +107 -0
  148. data/source/bzs/example/updateRecords.cpp +99 -0
  149. data/source/bzs/example/updateRecords_c.cpp +71 -0
  150. data/source/bzs/example/update_with_transaction.cpp +104 -0
  151. data/source/bzs/example/update_with_transaction_c.cpp +80 -0
  152. data/source/bzs/netsvc/client/tcpClient.cpp +226 -0
  153. data/source/bzs/netsvc/client/tcpClient.h +489 -0
  154. data/source/bzs/netsvc/server/IAppModule.h +94 -0
  155. data/source/bzs/netsvc/server/iserver.h +65 -0
  156. data/source/bzs/netsvc/server/serverCpt.cpp +522 -0
  157. data/source/bzs/netsvc/server/serverCpt.h +88 -0
  158. data/source/bzs/netsvc/server/serverPipe.cpp +705 -0
  159. data/source/bzs/netsvc/server/serverPipe.h +96 -0
  160. data/source/bzs/netsvc/server/serverTpool.cpp +416 -0
  161. data/source/bzs/netsvc/server/serverTpool.h +84 -0
  162. data/source/bzs/rtl/benchmark.cpp +96 -0
  163. data/source/bzs/rtl/benchmark.h +65 -0
  164. data/source/bzs/rtl/datetime.cpp +375 -0
  165. data/source/bzs/rtl/datetime.h +53 -0
  166. data/source/bzs/rtl/debuglog.cpp +106 -0
  167. data/source/bzs/rtl/debuglog.h +97 -0
  168. data/source/bzs/rtl/exception.h +116 -0
  169. data/source/bzs/rtl/stl_uty.cpp +35 -0
  170. data/source/bzs/rtl/stl_uty.h +29 -0
  171. data/source/bzs/rtl/stringBuffers.cpp +101 -0
  172. data/source/bzs/rtl/stringBuffers.h +58 -0
  173. data/source/bzs/rtl/strtrim.cpp +135 -0
  174. data/source/bzs/rtl/strtrim.h +46 -0
  175. data/source/bzs/test/tdclatl/bench_tdclatl.js +445 -0
  176. data/source/bzs/test/tdclrb/bench_tdclcpp.rb +375 -0
  177. data/source/bzs/test/tdclrb/prepare.rb +226 -0
  178. data/source/bzs/test/tdclrb/transactd_datetime_spec.rb +172 -0
  179. data/source/bzs/test/tdclrb/transactd_kanjischema_spec.rb +208 -0
  180. data/source/bzs/test/tdclrb/transactd_spec.rb +1536 -0
  181. data/source/bzs/test/transactdBench/transactdBench.cpp +430 -0
  182. data/source/bzs/test/transactdBench/transactdBench2.cpp +342 -0
  183. data/source/bzs/test/trdclengn/test_trdclengn.cpp +2030 -0
  184. data/source/global/tdclatl/Database.cpp +503 -0
  185. data/source/global/tdclatl/Database.h +139 -0
  186. data/source/global/tdclatl/DbDef.cpp +242 -0
  187. data/source/global/tdclatl/DbDef.h +79 -0
  188. data/source/global/tdclatl/Field.cpp +92 -0
  189. data/source/global/tdclatl/Field.h +59 -0
  190. data/source/global/tdclatl/FieldDef.cpp +238 -0
  191. data/source/global/tdclatl/FieldDef.h +87 -0
  192. data/source/global/tdclatl/Flags.cpp +111 -0
  193. data/source/global/tdclatl/Flags.h +55 -0
  194. data/source/global/tdclatl/KeyDef.cpp +51 -0
  195. data/source/global/tdclatl/KeyDef.h +55 -0
  196. data/source/global/tdclatl/KeySegment.cpp +55 -0
  197. data/source/global/tdclatl/Table.cpp +600 -0
  198. data/source/global/tdclatl/Table.h +144 -0
  199. data/source/global/tdclatl/TableDef.cpp +291 -0
  200. data/source/global/tdclatl/TableDef.h +86 -0
  201. data/source/global/tdclatl/TdVersion.cpp +74 -0
  202. data/source/global/tdclatl/TdVersion.h +54 -0
  203. data/source/global/tdclatl/_IDatabaseEvents_CP.h +113 -0
  204. data/source/global/tdclatl/dllmain.cpp +30 -0
  205. data/source/global/tdclatl/dllmain.h +27 -0
  206. data/source/global/tdclatl/keySegment.h +57 -0
  207. data/source/global/tdclatl/resource.h +0 -0
  208. data/source/global/tdclatl/stdafx.cpp +2 -0
  209. data/source/global/tdclatl/stdafx.h +25 -0
  210. data/source/global/tdclatl/targetver.h +4 -0
  211. data/source/global/tdclatl/tdclatl.cpp +68 -0
  212. data/source/global/tdclatl/tdclatl.def +10 -0
  213. data/source/global/tdclatl/tdclatl.idl +1035 -0
  214. data/source/linux/charsetConvert.h +112 -0
  215. data/source/linux/linuxTypes.h +33 -0
  216. data/source/linux/tchar.h +428 -0
  217. data/transactd.gemspec +97 -0
  218. 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
+