1 /***************************************************************************
2 * Copyright (C) 2007 by Prabakaran Thirumalai *
3 * praba_tuty@yahoo.com *
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. *
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. *
15 ***************************************************************************/
17 #include <Statement.h>
18 #include <TableImpl.h>
20 AlterTblStatement::AlterTblStatement()
22 bindFieldValues
= NULL
;
27 AlterTblStatement::~AlterTblStatement()
29 if (table
) { table
->close(); table
= NULL
; }
31 for(int i
=0;i
<totalFields
;i
++)
33 free(bindFieldValues
[i
]);
35 free(bindFieldValues
); bindFieldValues
= NULL
;
39 DbRetVal
AlterTblStatement::resolve()
42 altType
= parsedData
->getAlterType();
43 if(altType
== ALTERMODIFY
)
45 printError(ErrUnknown
, " NOT Done \n");
48 rv
= resolveForAddDropColumn();
52 DbRetVal
AlterTblStatement::execute(int &rowsAffected
)
55 DatabaseManagerImpl
*dmgr
= (DatabaseManagerImpl
*)dbMgr
;
56 IsolationLevel iso
= dmgr
->txnMgr()->getIsoLevel();
57 rv
= dmgr
->txnMgr()->rollback(dmgr
->lockMgr());
58 rv
= dmgr
->txnMgr()->startTransaction(dmgr
->lockMgr(),iso
);
60 if( altType
== ALTERTABLERENAME
)
62 rv
= dbMgr
->renameTable(parsedData
->getTableName(), parsedData
->getIndexName());
64 }else if( altType
== ALTERFIELDRENAME
)
66 if (strcmp(parsedData
->getIndexName(),parsedData
->getPKTableName())==0)
68 rv
= dbMgr
->renameField(parsedData
->getTableName(), parsedData
->getIndexName(),parsedData
->getPKTableName());
70 }else if(ALTERINDEXRENAME
== altType
){
71 rv
= dbMgr
->renameIndex(parsedData
->getTableName(), parsedData
->getIndexName());
74 rv
= executeForAddDropColumn(rowsAffected
);
78 DbRetVal
AlterTblStatement::resolveForAddDropColumn()
81 if( altType
== ALTERTABLERENAME
|| altType
== ALTERFIELDRENAME
|| altType
== ALTERINDEXRENAME
) return OK
;
82 table
= dbMgr
->openTable(parsedData
->getTableName());
85 printError(ErrNotExists
, "Unable to open the table:Table not exists");
88 List fNameList
= table
->getFieldNameList();
89 FieldList extraFldList
= parsedData
->getCreFldList() ;
90 ListIterator fNameIter
= fNameList
.getIterator();
91 FieldInfo
*info
= new FieldInfo();
92 int fcount
= 1; void *valBuf
; int ret
=0;
93 Identifier
*elem
= NULL
;
94 noOfOldTabFld
= fNameList
.size();
95 totalFields
= noOfOldTabFld
+ extraFldList
.size();
96 bindFieldValues
= (void**) malloc( totalFields
* sizeof(char*));
97 memset(bindFieldValues
, 0, totalFields
* sizeof(char*));
98 char fldName
[IDENTIFIER_LENGTH
];
100 while (fNameIter
.hasElement())
102 elem
= (Identifier
*) fNameIter
.nextElement();
103 table
->getFieldInfo((const char*)elem
->name
, info
);
104 Table::getFieldNameAlone(elem
->name
,fldName
);
105 //TODO :: Should free
106 valBuf
= AllDataType::alloc(info
->type
, info
->length
);
107 table
->bindFld(elem
->name
, valBuf
);
108 if(altType
== ALTERDROP
&& 0 == strcmp(parsedData
->getIndexName(),fldName
)){
109 bindFieldValues
[totalFields
-i
] = valBuf
; //Store Last
113 bindFieldValues
[fcount
-1] = valBuf
;
114 if (info
->type
== typeVarchar
|| info
->type
== typeString
)
117 ret
= tblDef
.addField(fldName
,info
->type
, info
->length
, info
->defaultValueBuf
, info
->isNull
, info
->isAutoIncrement
);
120 printError(ErrUnknown
, "Error while adding field");
128 while (fNameIter
.hasElement())
130 delete (Identifier
*) fNameIter
.nextElement();
133 if(altType
== ALTERDROP
)
138 FieldIterator iter
= extraFldList
.getIterator();
139 FieldName
*name
= NULL
;
140 ListIterator nIter
= parsedData
->getFieldNameList().getIterator();
141 while (iter
.hasElement())
143 FieldDef
*fDef
= iter
.nextElement();
145 while (nIter
.hasElement())
147 name
= (FieldName
*)nIter
.nextElement();
148 if (strcmp(name
->fldName
, fDef
->fldName_
) == 0) fDef
->isNull_
= true;
150 if (fDef
->type_
== typeVarchar
|| fDef
->type_
== typeString
) {
152 //varchar and char require \0 to be stored at the end
154 if (!fDef
->isDefault_
|| fDef
->isDefault_
&& fDef
->defaultValueBuf_
[0] == '\0') {
155 ret
= tblDef
.addField(fDef
->fldName_
, fDef
->type_
, fDef
->length_
,
156 NULL
,fDef
->isNull_
,fDef
->isAutoIncrement_
);
158 ret
= tblDef
.addField(fDef
->fldName_
, fDef
->type_
, fDef
->length_
,
159 fDef
->defaultValueBuf_
,fDef
->isNull_
,fDef
->isAutoIncrement_
);
163 printError(ErrUnknown
, "Error while adding field");
167 valBuf
= AllDataType::alloc(fDef
->type_
, fDef
->length_
);
168 bindFieldValues
[fcount
-1] = valBuf
;
174 DbRetVal
AlterTblStatement::executeForAddDropColumn(int &rowsAffected
)
177 char tblName
[IDENTIFIER_LENGTH
];
178 sprintf(tblName
,"%s_temp",parsedData
->getTableName());
179 rv
= dbMgr
->createTable(tblName
, tblDef
);
180 if (rv
!= OK
) return rv
;
181 rv
= createIndex(parsedData
->getTableName(),tblName
);
183 dbMgr
->dropTable(tblName
);
186 //TODO:Create Foreign Key Info
187 Table
*tempTable
= dbMgr
->openTable(tblName
);
188 List fNameList
= tempTable
->getFieldNameList();
189 ListIterator fNameIter
= fNameList
.getIterator();
190 FieldInfo
*info
= new FieldInfo();
191 int fcount
= 1; void *valBuf
;
192 Identifier
*elem
= NULL
;
193 while (fNameIter
.hasElement())
195 elem
= (Identifier
*) fNameIter
.nextElement();
196 tempTable
->getFieldInfo((const char*)elem
->name
, info
);
197 valBuf
= bindFieldValues
[fcount
-1];
198 tempTable
->bindFld(elem
->name
, valBuf
);
201 table
->setCondition(NULL
);
202 rv
= table
->execute();
205 dbMgr
->closeTable(tempTable
);
206 dbMgr
->dropTable(tblName
);
212 int extraField
= totalFields
- noOfOldTabFld
;
213 tuple
= (char*)table
->fetch();
214 if (tuple
== NULL
) {break;}
218 tempTable
->markFldNull(noOfOldTabFld
+i
);
221 rv
= tempTable
->insertTuple();
225 dbMgr
->closeTable(tempTable
);
226 dbMgr
->dropTable(tblName
);
229 char tblName1
[IDENTIFIER_LENGTH
];
230 sprintf(tblName1
,"%s_temp2",parsedData
->getTableName());
231 rv
= dbMgr
->renameTable(parsedData
->getTableName(),tblName1
);
233 dbMgr
->closeTable(tempTable
);
234 dbMgr
->dropTable(tblName
);
237 rv
= dbMgr
->renameTable(tblName
,parsedData
->getTableName());
239 dbMgr
->renameTable(tblName1
,parsedData
->getTableName());
240 dbMgr
->closeTable(tempTable
);
241 dbMgr
->dropTable(tblName
);
244 rv
= dbMgr
->dropTable(tblName1
);
246 dbMgr
->renameTable(tblName1
,parsedData
->getTableName());
247 dbMgr
->closeTable(tempTable
);
248 dbMgr
->dropTable(tblName
);
253 DbRetVal
AlterTblStatement::createIndex(const char *oldName
,const char *newName
)
256 CatalogTableINDEXFIELD
cIndexField(((DatabaseManagerImpl
*)dbMgr
)->sysDb());
257 ListIterator iter
= cIndexField
.getIndexListIterater((char*)oldName
);
258 IndexInfoForDriver
*info
=NULL
;
259 char name
[IDENTIFIER_LENGTH
]="";
260 char indName
[IDENTIFIER_LENGTH
]="";
261 char tempIndexName
[IDENTIFIER_LENGTH
] ="";
262 sprintf(tempIndexName
, "%s_idx1_Primary", oldName
);
263 bool shouldCreateIndex
= false;
264 bool isFirstEntry
=true;
265 HashIndexInitInfo
*idxInfo
= NULL
, *indexInfo2
= NULL
;
266 while(iter
.hasElement())
268 if(shouldCreateIndex
)
270 if(idxInfo
->isPrimary
&& 0 == strcmp(info
->indexName
,tempIndexName
))
271 sprintf(indName
, "%s_idx1_Primary", newName
);
272 rv
= dbMgr
->createIndex(indName
, idxInfo
);
279 shouldCreateIndex
= false;
282 info
= (IndexInfoForDriver
*) iter
.nextElement();
283 if((0 == strcmp(info
->indexName
,indName
)))
285 if(idxInfo
) idxInfo
->list
.append(info
->fieldName
);
286 else printf("should not happen\n");
288 idxInfo
= new HashIndexInitInfo();
289 strcpy(idxInfo
->tableName
, newName
);
290 strcpy(indName
,info
->indexName
);
291 if(!isFirstEntry
)shouldCreateIndex
=true;
292 isFirstEntry
= false;
293 idxInfo
->indType
=(IndexType
) info
->type
;
294 idxInfo
->isPrimary
= info
->isPrimary
;
295 idxInfo
->isUnique
= info
->isUnique
;
296 idxInfo
->list
.append(info
->fieldName
);
299 if (idxInfo
== NULL
) return OK
;
300 if(idxInfo
->isPrimary
&& 0 == strcmp(info
->indexName
,tempIndexName
))
301 sprintf(indName
, "%s_idx1_Primary", newName
);
302 rv
= dbMgr
->createIndex(indName
, idxInfo
);
313 DbRetVal
AlterTblStatement::resolveForModifyColumn()