1 /* Copyright (c) 2003-2005 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
17 #include <NDBT_Test.hpp>
29 for(size_t i
= 0; i
< attriblist
.size(); i
++){
33 void buildAttribList(const NdbDictionary::Table
* pTab
);
34 Vector
<Attrib
*> attriblist
;
38 // Functions that help out in testing that we may call
39 // scan functions in wrong order etc
40 // and receive a proper errormessage
43 ScanFunctions(const NdbDictionary::Table
& _tab
) : tab(_tab
){
48 ExecuteScanWithOutOpenScan
,
50 OnlyOneOpBeforeOpenScan
,
53 CheckInactivityTimeOut
,
54 CheckInactivityBeforeClose
,
60 int scanReadFunctions(Ndb
* pNdb
,
66 const NdbDictionary::Table
& tab
;
72 ScanFunctions::scanReadFunctions(Ndb
* pNdb
,
78 const int retryMax
= 100;
81 NdbConnection
*pTrans
= 0;
82 NdbScanOperation
*pOp
= 0;
85 if (retryAttempt
>= retryMax
){
86 g_err
<< "ERROR: has retried this operation " << retryAttempt
87 << " times, failing!" << endl
;
91 pTrans
= pNdb
->startTransaction();
93 const NdbError err
= pNdb
->getNdbError();
94 if (err
.status
== NdbError::TemporaryError
){
96 NdbSleep_MilliSleep(50);
104 // Execute the scan without defining a scan operation
105 pOp
= pTrans
->getNdbScanOperation(tab
.getName());
107 ERR(pTrans
->getNdbError());
108 pNdb
->closeTransaction(pTrans
);
112 if( pOp
->readTuples(exclusive
?
113 NdbScanOperation::LM_Exclusive
:
114 NdbScanOperation::LM_Read
) ) {
115 ERR(pTrans
->getNdbError());
116 pNdb
->closeTransaction(pTrans
);
121 if (action
== OnlyOpenScanOnce
){
122 // Call openScan one more time when it's already defined
123 if( pOp
->readTuples(NdbScanOperation::LM_Read
) ) {
124 ERR(pTrans
->getNdbError());
125 pNdb
->closeTransaction(pTrans
);
130 if (action
==EqualAfterOpenScan
){
131 check
= pOp
->equal(tab
.getColumn(0)->getName(), 10);
133 ERR(pTrans
->getNdbError());
134 pNdb
->closeTransaction(pTrans
);
139 check
= pOp
->interpret_exit_ok();
141 ERR(pTrans
->getNdbError());
142 pNdb
->closeTransaction(pTrans
);
146 for(int a
= 0; a
<tab
.getNoOfColumns(); a
++){
147 if(pOp
->getValue(tab
.getColumn(a
)->getName()) == NULL
) {
148 ERR(pTrans
->getNdbError());
149 pNdb
->closeTransaction(pTrans
);
154 check
= pTrans
->execute(NoCommit
);
156 ERR(pTrans
->getNdbError());
157 pNdb
->closeTransaction(pTrans
);
161 int abortCount
= records
/ 10;
162 bool abortTrans
= (action
==CloseWithoutStop
);
165 eof
= pOp
->nextResult();
170 if (abortCount
== rows
&& abortTrans
== true){
171 g_info
<< "Scan is aborted after "<<abortCount
<<" rows" << endl
;
173 if (action
!= CloseWithoutStop
){
174 // Test that we can closeTrans without stopScan
177 ERR(pTrans
->getNdbError());
178 pNdb
->closeTransaction(pTrans
);
184 pNdb
->closeTransaction(pTrans
);
188 if(action
== CheckInactivityTimeOut
){
189 if ((rows
% (records
/ 10)) == 0){
190 // Sleep for a long time before calling nextScanResult
193 g_info
<< "Sleeping "<<sleepTime
<<" secs " << endl
;
194 NdbSleep_SecSleep(sleepTime
);
198 eof
= pOp
->nextResult();
201 const NdbError err
= pTrans
->getNdbError();
203 if (err
.status
== NdbError::TemporaryError
){
206 // Be cruel, call nextScanResult after error
207 for(int i
=0; i
<10; i
++){
208 eof
= pOp
->nextResult();
210 g_err
<< "nextScanResult returned eof = " << eof
<< endl
211 << " That is an error when there are no more records" << endl
;
217 pNdb
->closeTransaction(pTrans
);
218 NdbSleep_MilliSleep(50);
220 g_info
<< "Starting over" << endl
;
222 // If test is CheckInactivityTimeOut
223 // error 296 is expected
224 if ((action
== CheckInactivityTimeOut
) &&
231 pNdb
->closeTransaction(pTrans
);
235 if (action
== NextScanWhenNoMore
){
236 g_info
<< "Calling nextScanresult when there are no more records" << endl
;
237 for(int i
=0; i
<10; i
++){
238 eof
= pOp
->nextResult();
240 g_err
<< "nextScanResult returned eof = " << eof
<< endl
241 << " That is an error when there are no more records" << endl
;
247 if(action
== CheckInactivityBeforeClose
){
248 // Sleep for a long time before calling close
249 g_info
<< "NdbSleep_SecSleep(5) before close transaction" << endl
;
250 NdbSleep_SecSleep(5);
252 if(action
== NoCloseTransaction
)
253 g_info
<< "Forgetting to close transaction" << endl
;
255 pNdb
->closeTransaction(pTrans
);
257 g_info
<< rows
<< " rows have been read" << endl
;
258 if (records
!= 0 && rows
!= records
){
259 g_err
<< "Check expected number of records failed" << endl
260 << " expected=" << records
<<", " << endl
261 << " read=" << rows
<< endl
;
272 void AttribList::buildAttribList(const NdbDictionary::Table
* pTab
){
276 // Build attrib definitions that describes which attributes to read
277 // Try to build strange combinations, not just "all" or all PK's
279 // Scan without reading any attributes
281 attr
->numAttribs
= 0;
282 attriblist
.push_back(attr
);
284 for(i
= 1; i
< pTab
->getNoOfColumns(); i
++){
286 attr
->numAttribs
= i
;
287 for(int a
= 0; a
<i
; a
++)
288 attr
->attribs
[a
] = a
;
289 attriblist
.push_back(attr
);
291 for(i
= pTab
->getNoOfColumns()-1; i
> 0; i
--){
293 attr
->numAttribs
= i
;
294 for(int a
= 0; a
<i
; a
++)
295 attr
->attribs
[a
] = a
;
296 attriblist
.push_back(attr
);
298 for(i
= pTab
->getNoOfColumns(); i
> 0; i
--){
300 attr
->numAttribs
= pTab
->getNoOfColumns() - i
;
301 for(int a
= 0; a
<pTab
->getNoOfColumns() - i
; a
++)
302 attr
->attribs
[a
] = pTab
->getNoOfColumns()-a
-1;
303 attriblist
.push_back(attr
);
305 for(i
= 1; i
< pTab
->getNoOfColumns(); i
++){
307 attr
->numAttribs
= pTab
->getNoOfColumns() - i
;
308 for(int a
= 0; a
<pTab
->getNoOfColumns() - i
; a
++)
309 attr
->attribs
[a
] = pTab
->getNoOfColumns()-a
-1;
310 attriblist
.push_back(attr
);
312 for(i
= 1; i
< pTab
->getNoOfColumns(); i
++){
314 attr
->numAttribs
= 2;
315 for(int a
= 0; a
<2; a
++){
316 attr
->attribs
[a
] = i
%pTab
->getNoOfColumns();
318 attriblist
.push_back(attr
);
323 attr
->numAttribs
= 1;
324 attr
->attribs
[0] = pTab
->getNoOfColumns()-1;
325 attriblist
.push_back(attr
);
329 attr
->numAttribs
= 2;
330 attr
->attribs
[0] = pTab
->getNoOfColumns()-1;
331 attr
->attribs
[1] = 0;
332 attriblist
.push_back(attr
);
336 attr
->numAttribs
= 2;
337 attr
->attribs
[0] = 0;
338 attr
->attribs
[1] = pTab
->getNoOfColumns()-1;
339 attriblist
.push_back(attr
);
342 for(size_t j
= 0; j
< attriblist
.size(); j
++){
344 g_info
<< attriblist
[j
]->numAttribs
<< ": " ;
345 for(int a
= 0; a
< attriblist
[j
]->numAttribs
; a
++)
346 g_info
<< attriblist
[j
]->attribs
[a
] << ", ";