*** empty log message ***
[csql.git] / src / sqllog / Recover.cxx
blob1ded0e441446386ebcb8c86ef65ceee6de419c08
1 /**************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #include <os.h>
21 #include <Recover.h>
23 void Recovery::addToHashTable(int stmtID, AbsSqlStatement* sHdl,
24 char *stmtstr)
26 int bucketNo = stmtID % STMT_BUCKET_SIZE;
27 printDebug(DM_Recovery, "Inside addToHashTable %x", stmtBuckets);
28 StmtBucket *buck = (StmtBucket *) stmtBuckets;
29 StmtBucket *stmtBucket = &buck[bucketNo];
30 StmtNode *node = new StmtNode();
31 node->stmtId = stmtID;
32 node->stmt = sHdl;
33 strcpy(node->stmtstr, stmtstr);
34 stmtBucket->bucketList.append(node);
35 return;
38 void Recovery::removeFromHashTable(int stmtID)
40 int bucketNo = stmtID % STMT_BUCKET_SIZE;
41 StmtBucket *buck = (StmtBucket *) stmtBuckets;
42 StmtBucket *stmtBucket = &buck[bucketNo];
43 StmtNode *node = NULL, *delNode = NULL;
44 ListIterator it = stmtBucket->bucketList.getIterator();
45 while(it.hasElement()) {
46 node = (StmtNode *) it.nextElement();
47 if(stmtID == node->stmtId) { delNode = node; break; }
49 it.reset();
50 if (delNode != NULL) {
51 stmtBucket->bucketList.remove(delNode);
52 delete delNode;
54 return;
57 AbsSqlStatement* Recovery::getStmtFromHashTable(int stmtId)
59 int bucketNo = stmtId % STMT_BUCKET_SIZE;
60 StmtBucket *buck = (StmtBucket *) stmtBuckets;
61 StmtBucket *stmtBucket = &buck[bucketNo];
62 if (stmtBucket == NULL) return NULL;
63 StmtNode *node = NULL;
64 ListIterator it = stmtBucket->bucketList.getIterator();
65 while(it.hasElement()) {
66 node = (StmtNode *) it.nextElement();
67 if(stmtId == node->stmtId) {
68 SqlStatement *sqlStmt = (SqlStatement*)node->stmt;
69 if (!sqlStmt->isPrepared()) sqlStmt->prepare(node->stmtstr);
70 return node->stmt;
73 return NULL;
76 bool Recovery::isStmtInHashTable(int stmtId)
78 int bucketNo = stmtId % STMT_BUCKET_SIZE;
79 StmtBucket *buck = (StmtBucket *) stmtBuckets;
80 StmtBucket *stmtBucket = &buck[bucketNo];
81 if (stmtBucket == NULL) return false;
82 StmtNode *node = NULL;
83 ListIterator it = stmtBucket->bucketList.getIterator();
84 while(it.hasElement()) {
85 node = (StmtNode *) it.nextElement();
86 if(stmtId == node->stmtId) {
87 SqlStatement *sqlStmt = (SqlStatement*)node->stmt;
88 if (sqlStmt->isPrepared()) return true;
89 else break;
92 return false;
95 void Recovery::freeAllStmtHandles()
97 if (NULL == stmtBuckets) return;
98 StmtBucket *buck = (StmtBucket *) stmtBuckets;
99 StmtNode *node = NULL;
100 for (int i=0; i <STMT_BUCKET_SIZE; i++)
102 StmtBucket *stmtBucket = &buck[i];
103 if (stmtBucket == NULL) continue;
104 ListIterator it = stmtBucket->bucketList.getIterator();
105 while(it.hasElement()) {
106 node = (StmtNode *) it.nextElement();
107 node->stmt->free();
108 delete node->stmt;
111 ::free(stmtBuckets);
112 stmtBuckets = NULL;
115 DbRetVal Recovery::filterAndWriteStmtLogs()
117 struct stat st;
118 char fName[MAX_FILE_LEN];
119 sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile());
120 file_desc fdRead = os::openFile(fName, fileOpenReadOnly,0);
121 if ((file_desc)-1 == fdRead) { return OK; }
122 if (::stat(fName, &st) == -1) {
123 printError(ErrSysInternal, "Unable to retrieve stmt log file size");
124 os::closeFile(fdRead);
125 return ErrSysInternal;
127 if (st.st_size ==0) {
128 os::closeFile(fdRead);
129 return OK;
131 void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fdRead, 0);
132 if ((void*)MAP_FAILED == startAddr) {
133 printError(ErrSysInternal, "Unable to mmap stmt log file\n");
134 return ErrSysInternal;
136 sprintf(fName, "%s/csql.db.stmt1", Conf::config.getDbFile());
137 int fd = os::openFileForAppend(fName, O_CREAT|O_TRUNC);
138 char *iter = (char*)startAddr;
139 char *logStart = NULL, *logEnd = NULL;
140 int logType;
141 int stmtID;
142 int len =0, ret =0;
143 DbRetVal rv = OK;
144 while(true) {
145 if (iter - (char*)startAddr >= st.st_size) break;
146 logType = *(int*)iter;
147 logStart = iter;
148 if (logType == -1) { //prepare
149 iter = iter + sizeof(int);
150 len = *(int*) iter;
151 iter = iter + 2 * sizeof(int);
152 stmtID = *(int*)iter;
153 iter = logStart+ len;
154 ret =0;
155 if (isStmtInHashTable(stmtID))
156 ret = os::write(fd, logStart, len);
157 if (-1 == ret) {
158 printError(ErrSysInternal, "Unable to write statement logs");
161 else if(logType == -3) { //free
162 iter = logStart + 4 *sizeof(int);
163 }else{
164 printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType);
165 rv = ErrSysInternal;
166 break;
169 os::close(fd);
170 os::munmap((char*)startAddr, st.st_size);
171 os::closeFile(fdRead);
172 char cmd[MAX_FILE_LEN *2];
173 sprintf(cmd, "mv %s/csql.db.stmt1 %s/csql.db.stmt",
174 Conf::config.getDbFile(), Conf::config.getDbFile());
175 ret = ::system(cmd);
176 return rv;
179 DbRetVal Recovery::readAndPopulateStmts(AbsSqlConnection *conn, bool list, bool interactive)
181 struct stat st;
182 char fName[MAX_FILE_LEN];
183 sprintf(fName, "%s/csql.db.stmt", Conf::config.getDbFile());
184 printDebug(DM_Recovery,"Statement Redo log filename is :%s\n", fName);
185 file_desc fd = os::openFile(fName, fileOpenReadOnly, 0);
186 if ((file_desc)-1 == fd) {
187 printDebug(DM_Recovery, "No redo log file found");
188 return OK;
190 if (::stat(fName, &st) == -1) {
191 printError(ErrSysInternal, "Unable to retrieve stmt log file size");
192 os::closeFile(fd);
193 return ErrSysInternal;
195 if (NULL != stmtBuckets)
197 printError(ErrSysInternal, "stmtBuckets already populated");
198 os::closeFile(fd);
199 return ErrSysInternal;
201 stmtBuckets = (void*) ::malloc (STMT_BUCKET_SIZE * sizeof(StmtBucket));
202 printDebug(DM_Recovery, "stmtBuckets allocated %x", stmtBuckets);
203 memset(stmtBuckets, 0, STMT_BUCKET_SIZE * sizeof(StmtBucket));
204 if (st.st_size ==0) {
205 printError(ErrNote, "No Statement logs found during recovery");
206 os::closeFile(fd);
207 return OK;
209 void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fd, 0);
210 if ((void*)MAP_FAILED == startAddr) {
211 printError(ErrSysInternal, "Unable to mmap stmt log file\n");
212 ::free(stmtBuckets);
213 stmtBuckets = NULL;
214 os::closeFile(fd);
215 return ErrSysInternal;
217 DbRetVal rv = iterateStmtLogs(conn, startAddr, st.st_size, list, interactive);
218 os::munmap((char*)startAddr, st.st_size);
219 os::closeFile(fd);
220 return rv;
223 DbRetVal Recovery::iterateStmtLogs(AbsSqlConnection *conn, void *startAddr, int size, bool list, bool interactive)
225 char *iter = (char*)startAddr;
226 void *value = NULL;
227 int logType, eType;
228 int stmtID;
229 int txnID;
230 int len, ret, retVal =0;
231 int loglen;
232 char stmtString[SQL_STMT_LEN];
233 DbRetVal rv = OK;
234 while(true) {
235 if (iter - (char*)startAddr >= size) break;
236 logType = *(int*)iter;
237 if (logType == -1) { //prepare
238 iter = iter + sizeof(int);
239 txnID = *(int*) iter; iter += sizeof(int);
240 loglen = *(int*) iter; iter += sizeof(int);
241 stmtID = *(int*)iter;
242 iter = iter + sizeof(int);
243 len = *(int*)iter;
244 iter = iter + sizeof(int);
245 strncpy(stmtString, iter, len);
246 iter = iter + len;
247 if (list) {
248 printf("PREPARE: SID:%d %s\n", stmtID, stmtString);
249 continue;
251 if (interactive) printf("STMTLOG PREPARE SID:%d %s\n", stmtID, stmtString);
252 AbsSqlStatement *csqlStmt = SqlFactory::createStatement(CSqlDirect);
253 csqlStmt->setConnection(conn);
254 SqlStatement *sqlStmt = (SqlStatement*)csqlStmt;
255 sqlStmt->setStmtString(stmtString);
256 addToHashTable(stmtID, csqlStmt, stmtString);
258 else if(logType == -3) { //free
259 iter = iter + sizeof(int);
260 txnID = *(int*) iter; iter += sizeof(int);
261 loglen = *(int*) iter; iter += sizeof(int);
262 stmtID = *(int*)iter;
263 iter = iter + sizeof(int);
264 if (list) {
265 printf("FREE: SID:%d TID:%d \n", stmtID, txnID);
266 continue;
268 }else{
269 printError(ErrSysInternal, "Stmt Redo log file corrupted: logType:%d", logType);
270 rv = ErrSysInternal;
271 break;
274 return rv;
277 #if (defined MMDB && defined EMBED)
279 DbRetVal Recovery::recoverCsqlDB(SqlConnection *conn)
281 DbRetVal rv = OK;
282 char dbRedoFileName[MAX_FILE_LEN];
283 char dbChkptSchema[MAX_FILE_LEN];
284 char dbChkptMap[MAX_FILE_LEN];
285 char dbChkptData[MAX_FILE_LEN];
286 char dbBackupFile[MAX_FILE_LEN];
287 char cmd[IDENTIFIER_LENGTH];
288 //check for check point file if present recover
289 sprintf(dbChkptSchema, "%s/db.chkpt.schema1", Conf::config.getDbFile());
290 if (FILE *file = fopen(dbChkptSchema, "r")) {
291 fclose(file);
292 sprintf(cmd, "cp -f %s %s/db.chkpt.schema", dbChkptSchema,
293 Conf::config.getDbFile());
294 int ret = system(cmd);
295 if (ret != 0) return ErrOS;
297 sprintf(dbChkptMap, "%s/db.chkpt.map1", Conf::config.getDbFile());
298 if (FILE *file = fopen(dbChkptMap, "r")) {
299 fclose(file);
300 sprintf(cmd, "cp -f %s %s/db.chkpt.map", dbChkptMap,
301 Conf::config.getDbFile());
302 int ret = system(cmd);
303 if (ret != 0) return ErrOS;
305 int chkptID= Database::getCheckpointID();
306 sprintf(dbChkptData, "%s/db.chkpt.data%d", Conf::config.getDbFile(),
307 chkptID);
308 sprintf(dbBackupFile, "%s/db.chkpt.data1", Conf::config.getDbFile());
309 FILE *fl = NULL;
310 if (!Conf::config.useMmap() && (fl = fopen(dbBackupFile, "r"))) {
311 fclose(fl);
312 sprintf(cmd, "cp %s/db.chkpt.data1 %s", Conf::config.getDbFile(),
313 dbChkptData);
314 int ret = system(cmd);
315 if (ret != 0) return ErrOS;
317 if (FILE *file = fopen(dbChkptData, "r")) {
318 fclose(file);
319 rv = recoverSystemAndUserDB(conn);
320 if (rv != OK) return rv;
323 //check for redo log file if present apply redo logs
324 sprintf(dbRedoFileName, "%s/csql.db.cur", Conf::config.getDbFile());
325 if (FILE *file = fopen(dbRedoFileName, "r"))
327 fclose(file);
328 rv = (DbRetVal) applyRedoLogs(dbRedoFileName, conn);
329 if (rv != OK) return rv;
330 DatabaseManager *dbMgr = conn->getConnObject().getDatabaseManager();
331 rv = dbMgr->checkPoint();
332 if (rv != OK)
334 printError(ErrSysInternal, "checkpoint failed after redo log apply");
335 return ErrOS;
338 return OK;
341 DbRetVal Recovery::recoverSystemAndUserDB(SqlConnection *conn)
343 DbRetVal rv = OK;
344 char schFile[1024];
345 sprintf(schFile, "%s/db.chkpt.schema", Conf::config.getDbFile());
346 if (FILE *file = fopen(schFile, "r")) {
347 rv = applySchemaFile(file, conn);
348 if (rv != OK) { fclose(file); return rv; }
350 DatabaseManager *dbMgr = conn->getConnObject().getDatabaseManager();
351 rv = dbMgr->recover();
352 return rv;
355 DbRetVal Recovery::applySchemaFile(FILE *fp, SqlConnection *conn)
357 char buf[8192];
358 char eof;
359 DbRetVal rv = OK;
360 SqlStatement *stmt = new SqlStatement();
361 while ((eof = getQueryFromSchemaFile(fp,buf)) != EOF) {
362 stmt->setConnection(conn);
363 rv = stmt->prepare(buf);
364 if (rv != OK) { delete stmt; return rv; }
365 int rows = 0;
366 stmt->execute(rows);
367 if (rv != OK) { stmt->free(); delete stmt; return rv; }
369 delete stmt;
370 return OK;
373 char Recovery::getQueryFromSchemaFile(FILE *fp, char *buf)
375 char c, *bufBegin=buf;
376 int charCnt=0;
377 while( (c=(char ) fgetc(fp)) != EOF && c != ';')
379 *buf++ = c; charCnt++;
380 if( charCnt == SQL_STMT_LEN ) {
381 printf("SQL Statement length is greater than %d. "
382 "Ignoring the statement.\n", SQL_STMT_LEN );
383 *bufBegin++ =';';
384 *bufBegin ='\0';
385 return 0;
388 *buf++ = ';';
389 *buf = '\0';
390 return c;
392 #endif
393 int Recovery::applyRedoLogs(char *redoFile, AbsSqlConnection *conn, bool list, bool interactive )
395 struct stat st;
396 DbRetVal rv = OK;
397 file_desc fd = os::openFile(redoFile, fileOpenReadOnly, 0);
398 if ((file_desc)-1 == fd) { return OK; }
399 if (fstat(fd, &st) == -1) {
400 printError(ErrSysInternal, "Unable to retrieve undo log file size");
401 os::closeFile(fd);
402 return 1;
404 if (st.st_size ==0) {
405 printError(ErrNote, "No Redo logs found during recovery");
406 readAndPopulateStmts(conn, list, interactive);
407 os::closeFile(fd);
408 return 0;
410 void *startAddr = os::mmap(NULL, st.st_size, mapProtRead, mapPrivate, fd, 0);
411 if (MAP_FAILED == startAddr) {
412 printf("Unable to read undo log file:mmap failed.\n");
413 return 3;
416 rv = readAndPopulateStmts(conn, list, interactive);
417 if (OK != rv)
419 printf("Unable to read stmt log file\n");
420 return 4;
423 iter = (char*)startAddr;
424 void *value = NULL;
425 int logType, eType;
426 int stmtID;
427 int txnID;
428 int len, ret, retVal =0;
429 int loglen;
430 char stmtString[SQL_STMT_LEN];
431 printDebug(DM_Recovery,"Redo log filename is :%s\n", redoFile);
432 while(true) {
433 if (iter - (char*)startAddr >= st.st_size) break;
434 logType = *(int*)iter;
435 if (logType == -1) { //prepare
436 rv = handlePrepare(conn, list, interactive);
437 if (rv != OK) {
438 printError(ErrSysInternal, "unable to handle prepare stmt");
439 retVal=1;
440 break;
443 else if(logType == -2) { //commit
444 rv = handleCommit(conn, startAddr, st.st_size, list, interactive);
445 if (ErrEndReached == rv)
447 printDebug(DM_Recovery, "During Commit processing, end redo log reached");
448 retVal=0;
449 break;
450 }else if (OK != rv) {
451 printError(ErrSysInternal, "unable to handle prepare stmt");
452 retVal=1;
453 break;
456 else if(logType == -3) { //free
457 handleFree(list, interactive);
459 else if(logType == -4) { //prepare and execute
460 handlePrepareAndExecute(conn, list, interactive);
461 } else {
462 printError(ErrSysInternal, "Redo log file corrupted: logType:%d", logType);
463 retVal=6;
464 break;
467 printDebug(DM_Recovery, "Before munmap");
468 os::munmap((char*)startAddr, st.st_size);
469 os::closeFile(fd);
470 if (!list) {
471 //when redo log list option is specified do not write statement logs
472 //it will block debugging and change the state at which problem
473 //occurred
474 printDebug(DM_Recovery, "Before filter and writestmt logs");
475 filterAndWriteStmtLogs();
476 printDebug(DM_Recovery, "Before freeallstmthandles");
477 freeAllStmtHandles();
479 return retVal;
481 DbRetVal Recovery::handlePrepare( AbsSqlConnection *conn, bool list, bool interactive)
483 char stmtString[SQL_STMT_LEN];
484 iter = iter + sizeof(int);
485 int txnID = *(int*) iter;
486 iter += sizeof(int);
487 int loglen = *(int*) iter;
488 iter += sizeof(int);
489 int stmtID = *(int*)iter;
490 iter = iter + sizeof(int);
491 int len = *(int*)iter;
492 iter = iter + sizeof(int);
493 strncpy(stmtString, iter, len);
494 iter = iter + len;
495 printDebug(DM_Recovery,"PREPARE: SID:%d %s\n", stmtID, stmtString);
496 if (list) {
497 printf("PREPARE: SID:%d %s\n", stmtID, stmtString);
498 return OK;
500 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
501 stmt->setConnection(conn);
502 if (interactive) printf("PREPARE %d : %s\n", stmtID, stmtString);
503 DbRetVal rv = stmt->prepare(stmtString);
504 if (rv != OK) {
505 printError(ErrSysInternal, "unable to prepare stmt:%s", stmtString);
506 return ErrSysInternal;
508 SqlStatement *sqlStmt = (SqlStatement*)stmt;
509 sqlStmt->setLoading(true);
510 addToHashTable(stmtID, stmt, stmtString);
511 printDebug(DM_Recovery,"Added to hashtable SID:%d ", stmtID);
512 return OK;
514 DbRetVal Recovery::handleCommit(AbsSqlConnection *conn, void *startAddr, long size, bool list, bool interactive)
516 conn->beginTrans();
517 iter = iter + sizeof(int);
518 int txnID = *(int*) iter; iter += sizeof(int);
519 int loglen = *(int*) iter; iter += sizeof(int);
520 char *curPtr = iter;
521 DbRetVal rv = OK;
522 int ret =0;
523 void *value = NULL;
524 while(true) {
525 printDebug(DM_Recovery, "Iter length %d\n", iter - curPtr);
526 if (iter - (char*)startAddr >= size) {
527 //file end reached
528 printDebug(DM_Recovery, "Redo log file end\n");
529 return ErrEndReached;
531 int stmtID = *(int*)iter;
532 printDebug(DM_Recovery, "stmtid %d\n", stmtID);
533 if (interactive) printf("EXEC %d :\n", stmtID);
534 iter = iter + sizeof(int);
535 int eType = *(int*)iter;
536 printDebug(DM_Recovery,"eType is %d\n", eType);
537 AbsSqlStatement *stmt = NULL;
538 if (!list) {
539 stmt = getStmtFromHashTable(stmtID);
540 if (NULL == stmt) {
541 printError(ErrSysInternal, "Unable to find in stmt hashtable");
542 return ErrSysInternal;
545 if (0 == eType) { //execute type
546 iter = iter + sizeof(int);
547 printDebug(DM_Recovery, "EXEC SID:%d TID:%d\n", stmtID, txnID);
548 if (list) {
549 printf("EXEC SID:%d TID:%d\n", stmtID, txnID);
550 if (*(int*)iter <0) break;
551 continue;
553 if (stmt) {
554 rv = stmt->execute(ret);
555 if (rv != OK) {
556 printError(ErrSysInternal, "unable to execute");
557 return ErrSysInternal;
559 } else {
560 printError(ErrSysInternal, "statement not found for %d\n",stmtID);
562 printDebug(DM_Recovery, "iter:%x value:%d", iter, *(int*)iter);
563 if (*(int*)iter <0) break;
564 } else if ( 1 == eType) { //set type
565 iter=iter+sizeof(int);
566 int pos = *(int*) iter;
567 iter=iter+sizeof(int);
568 int isNull = *(int *) iter;
569 iter=iter+sizeof(int);
570 if (isNull == 0) {
571 DataType type = (DataType)(*(int*)iter);
572 iter=iter+sizeof(int);
573 int len = *(int*) iter;
574 iter=iter+sizeof(int);
575 value = iter;
576 iter=iter+len;
577 printDebug(DM_Recovery, "SET SID:%d POS:%d ISNULL:FALSE TYPE:%d LEN:%d Value:", stmtID, pos, type, len);
578 if (list) {
579 printf("SET SID:%d POS:%d ISNULL:FALSE TYPE:%d LEN:%d Value:", stmtID, pos, type, len);
580 AllDataType::printVal(value, type, len);
581 printf("\n");
582 if (*(int*)iter <0) break;
583 continue;
585 SqlStatement::setParamValues(stmt, pos, type, len, value);
586 } else {
587 printDebug(DM_Recovery, "SET SID:%d POS:%d ISNULL:TRUE\n", stmtID, pos);
588 if (list) {
589 printf("SET SID:%d POS:%d ISNULL:TRUE\n", stmtID, pos);
590 continue;
592 stmt->setNull(pos);
594 if (*(int*)iter <0) break;
597 conn->commit();
598 return OK;
600 DbRetVal Recovery::handleFree(bool list, bool interactive)
602 iter = iter + sizeof(int);
603 int txnID = *(int*) iter; iter += sizeof(int);
604 int loglen = *(int*) iter; iter += sizeof(int);
605 int stmtID = *(int*)iter;
606 iter = iter + sizeof(int);
607 printDebug(DM_Recovery, "FREE SID:%d \n", stmtID);
608 if (list) {
609 printf("FREE SID:%d \n", stmtID);
610 return OK;
612 if (interactive) printf("FREE %d:\n", stmtID);
613 AbsSqlStatement *stmt = getStmtFromHashTable(stmtID);
614 if (stmt) {
615 stmt->free();
616 delete stmt;
617 removeFromHashTable(stmtID);
618 } else {
619 printError(ErrSysInternal, "statement not found for %d\n",stmtID);
621 return OK;
623 DbRetVal Recovery::handlePrepareAndExecute(AbsSqlConnection *conn, bool list, bool interactive)
625 int ret = 0;
626 DbRetVal rv = OK;
627 char stmtString[SQL_STMT_LEN];
628 iter = iter + sizeof(int);
629 int txnID = *(int*) iter; iter += sizeof(int);
630 int loglen = *(int*) iter; iter += sizeof(int);
631 int stmtID = *(int*)iter;
632 iter = iter + sizeof(int);
633 int len = *(int*)iter;
634 iter = iter + sizeof(int);
635 strncpy(stmtString, iter, len);
636 iter = iter + len;
637 printDebug(DM_Recovery, "EXECDIRECT SID:%d TID:%d STMT:%s\n", stmtID, txnID, stmtString);
638 if (list) {
639 printf("EXECDIRECT SID:%d TID:%d STMT:%s\n", stmtID, txnID, stmtString);
640 return OK;
642 AbsSqlStatement *stmt = SqlFactory::createStatement(CSqlDirect);
643 if ( NULL == stmt) {
644 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
645 return ErrSysInternal;
647 stmt->setConnection(conn);
648 if (interactive) printf("EXECDIRECT %d : %s\n", stmtID, stmtString);
649 rv = stmt->prepare(stmtString);
650 if (rv != OK) {
651 printError(ErrSysInternal, "unable to prepare:%s", stmtString);
652 stmt->free();
653 delete stmt;
654 return ErrSysInternal;
656 rv = stmt->execute(ret);
657 if(rv != OK) {
658 if (strlen(stmtString) > 6 &&
659 ( (strncasecmp(stmtString,"CREATE", 6) == 0) ||
660 (strncasecmp(stmtString,"DROP", 4) == 0) ||
661 (strncasecmp(stmtString,"RENAME", 6) == 0) ||
662 (strncasecmp(stmtString,"ALTER", 5) == 0)) ) {
663 return OK;
665 printError(ErrSysInternal, "unable to execute %s", stmtString);
666 stmt->free();
667 return ErrSysInternal;
669 stmt->free();
670 delete stmt;
671 return OK;