transactd 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+