Alter Table fixes.
[csql.git] / src / sql / AlterTblStatement.cxx
blob8a1fbf1177bbca2c988a2b80a1dfb10ed5a12470
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 ***************************************************************************/
16 #include <os.h>
17 #include <Statement.h>
18 #include <TableImpl.h>
20 AlterTblStatement::AlterTblStatement()
22 bindFieldValues = NULL;
23 table = NULL;
24 totalFields = 0 ;
27 AlterTblStatement::~AlterTblStatement()
29 if (table) { table->close(); table = NULL; }
30 if(totalFields){
31 for(int i=0;i<totalFields;i++)
33 free(bindFieldValues[i]);
35 free(bindFieldValues); bindFieldValues = NULL;
39 DbRetVal AlterTblStatement::resolve()
41 DbRetVal rv = OK;
42 table = dbMgr->openTable(parsedData->getTableName());
43 if (table == NULL)
45 printError(ErrNotExists, "Unable to open the table:Table not exists");
46 return ErrNotExists;
48 altType = parsedData->getAlterType();
49 if(altType == ALTERMODIFY)
51 printError(ErrUnknown, " NOT Done \n");
52 return ErrUnknown;
54 rv = resolveForAddDropColumn();
55 return rv;
58 DbRetVal AlterTblStatement::execute(int &rowsAffected)
60 DbRetVal rv = OK;
61 if( altType == ALTERTABLERENAME)
63 rv = dbMgr->renameTable(parsedData->getTableName(), parsedData->getIndexName());
64 return rv;
65 }else if( altType == ALTERFIELDRENAME)
67 if (strcmp(parsedData->getIndexName(),parsedData->getPKTableName())==0)
68 return OK;
69 rv = dbMgr->renameField(parsedData->getTableName(), parsedData->getIndexName(),parsedData->getPKTableName());
70 return rv;
72 rv = executeForAddDropColumn(rowsAffected);
73 return rv;
76 DbRetVal AlterTblStatement::resolveForAddDropColumn()
78 DbRetVal rv = OK;
79 if( altType == ALTERTABLERENAME || altType == ALTERFIELDRENAME) return OK;
80 List fNameList = table->getFieldNameList();
81 FieldList extraFldList = parsedData->getCreFldList() ;
82 ListIterator fNameIter = fNameList.getIterator();
83 FieldInfo *info = new FieldInfo();
84 int fcount = 1; void *valBuf; int ret=0;
85 Identifier *elem = NULL;
86 noOfOldTabFld = fNameList.size();
87 totalFields = noOfOldTabFld + extraFldList.size();
88 bindFieldValues = (void**) malloc( totalFields * sizeof(char*));
89 memset(bindFieldValues, 0, totalFields * sizeof(char*));
90 char fldName[IDENTIFIER_LENGTH];
91 int i = 1;
92 while (fNameIter.hasElement())
94 elem = (Identifier*) fNameIter.nextElement();
95 table->getFieldInfo((const char*)elem->name, info);
96 Table::getFieldNameAlone(elem->name,fldName);
97 //TODO :: Should free
98 valBuf = AllDataType::alloc(info->type, info->length);
99 table->bindFld(elem->name, valBuf);
100 if(altType == ALTERDROP && 0 == strcmp(parsedData->getIndexName(),fldName)){
101 bindFieldValues[totalFields-i] = valBuf; //Store Last
102 i--;
104 else {
105 bindFieldValues[fcount-1] = valBuf;
106 ret = tblDef.addField(fldName,info->type, info->length, info->defaultValueBuf, info->isNull, info->isAutoIncrement);
107 if( 0 != ret )
109 printError(ErrUnknown, "Error while adding field");
110 rv = ErrUnknown;
111 break;
113 fcount++;
116 fNameIter.reset();
117 while (fNameIter.hasElement())
119 delete (Identifier*) fNameIter.nextElement();
121 fNameList.reset();
122 if(altType == ALTERDROP)
124 delete info;
125 return rv;
127 FieldIterator iter = extraFldList.getIterator();
128 FieldName *name = NULL;
129 ListIterator nIter = parsedData->getFieldNameList().getIterator();
130 while (iter.hasElement())
132 FieldDef *fDef = iter.nextElement();
133 nIter.reset();
134 while (nIter.hasElement())
136 name = (FieldName*)nIter.nextElement();
137 if (strcmp(name->fldName, fDef->fldName_) == 0) fDef->isNull_ = true;
139 if (!fDef->isDefault_ || fDef->isDefault_ && fDef->defaultValueBuf_[0] == '\0') {
140 ret = tblDef.addField(fDef->fldName_, fDef->type_, fDef->length_,
141 NULL,fDef->isNull_,fDef->isAutoIncrement_);
142 } else {
143 ret = tblDef.addField(fDef->fldName_, fDef->type_, fDef->length_,
144 fDef->defaultValueBuf_,fDef->isNull_,fDef->isAutoIncrement_);
146 if( 0 != ret )
148 printError(ErrUnknown, "Error while adding field");
149 rv = ErrUnknown;
150 break;
152 valBuf = AllDataType::alloc(fDef->type_, fDef->length_);
153 bindFieldValues[fcount-1] = valBuf;
155 delete info;
156 return rv;
159 DbRetVal AlterTblStatement::executeForAddDropColumn(int &rowsAffected)
161 DbRetVal rv = OK;
162 char tblName[IDENTIFIER_LENGTH];
163 sprintf(tblName,"%s_temp",parsedData->getTableName());
164 rv = dbMgr->createTable(tblName, tblDef);
165 if (rv != OK) return rv;
166 rv = createIndex(parsedData->getTableName(),tblName);
167 if (rv != OK){
168 dbMgr->dropTable(tblName);
169 return rv;
171 //TODO:Create Foreign Key Info
172 Table *tempTable = dbMgr->openTable(tblName);
173 List fNameList = tempTable->getFieldNameList();
174 ListIterator fNameIter = fNameList.getIterator();
175 FieldInfo *info = new FieldInfo();
176 int fcount = 1; void *valBuf;
177 Identifier *elem = NULL;
178 while (fNameIter.hasElement())
180 elem = (Identifier*) fNameIter.nextElement();
181 tempTable->getFieldInfo((const char*)elem->name, info);
182 valBuf = bindFieldValues[fcount-1];
183 tempTable->bindFld(elem->name, valBuf);
184 fcount++;
186 table->setCondition(NULL);
187 rv = table->execute();
188 if (rv != OK)
190 dbMgr->closeTable(tempTable);
191 dbMgr->dropTable(tblName);
192 return rv;
194 void *tuple = NULL;
195 while(true)
197 int extraField = totalFields - noOfOldTabFld;
198 tuple = (char*)table->fetch();
199 if (tuple == NULL) {break;}
200 int i=1;
201 while(extraField--)
203 tempTable->markFldNull(noOfOldTabFld+i);
204 i++;
206 rv = tempTable->insertTuple();
207 if (rv != OK) break;
209 if (rv != OK){
210 dbMgr->closeTable(tempTable);
211 dbMgr->dropTable(tblName);
212 return rv;
214 char tblName1[IDENTIFIER_LENGTH];
215 sprintf(tblName1,"%s_temp2",parsedData->getTableName());
216 rv = dbMgr->renameTable(parsedData->getTableName(),tblName1);
217 if (rv != OK){
218 dbMgr->closeTable(tempTable);
219 dbMgr->dropTable(tblName);
220 return rv;
222 rv = dbMgr->renameTable(tblName,parsedData->getTableName());
223 if (rv != OK){
224 dbMgr->renameTable(tblName1,parsedData->getTableName());
225 dbMgr->closeTable(tempTable);
226 dbMgr->dropTable(tblName);
227 return rv;
229 rv = dbMgr->dropTable(tblName1);
230 if (rv != OK){
231 dbMgr->renameTable(tblName1,parsedData->getTableName());
232 dbMgr->closeTable(tempTable);
233 dbMgr->dropTable(tblName);
234 return rv;
236 return rv;
238 DbRetVal AlterTblStatement::createIndex(const char *oldName,const char *newName)
240 DbRetVal rv=OK;
241 CatalogTableINDEXFIELD cIndexField(((DatabaseManagerImpl *)dbMgr)->sysDb());
242 ListIterator iter = cIndexField.getIndexListIterater((char*)oldName);
243 IndexInfoForDriver *info=NULL;
244 char name[IDENTIFIER_LENGTH]="";
245 char indName[IDENTIFIER_LENGTH]="";
246 char tempIndexName[IDENTIFIER_LENGTH] ="";
247 sprintf(tempIndexName, "%s_idx1_Primary", oldName);
248 bool shouldCreateIndex = false;
249 bool isFirstEntry=true;
250 HashIndexInitInfo *idxInfo = NULL, *indexInfo2 = NULL;
251 while(iter.hasElement())
253 if(shouldCreateIndex)
255 if(idxInfo->isPrimary && 0 == strcmp(info->indexName,tempIndexName))
256 sprintf(indName, "%s_idx1_Primary", newName);
257 rv = dbMgr->createIndex(indName, idxInfo);
258 if (rv != OK)
260 delete idxInfo;
261 return rv;
263 delete idxInfo;
264 shouldCreateIndex = false;
265 idxInfo = NULL;
267 info = (IndexInfoForDriver *) iter.nextElement();
268 if((0 == strcmp(info->indexName,indName)))
270 if(idxInfo) idxInfo->list.append(info->fieldName);
271 else printf("should not happen\n");
272 }else{
273 idxInfo = new HashIndexInitInfo();
274 strcpy(idxInfo->tableName, newName);
275 strcpy(indName,info->indexName);
276 if(!isFirstEntry)shouldCreateIndex =true;
277 isFirstEntry = false;
278 idxInfo->indType =(IndexType) info->type;
279 idxInfo->isPrimary = info->isPrimary ;
280 idxInfo->isUnique = info->isUnique;
281 idxInfo->list.append(info->fieldName);
284 if (idxInfo == NULL) return OK;
285 if(idxInfo->isPrimary && 0 == strcmp(info->indexName,tempIndexName))
286 sprintf(indName, "%s_idx1_Primary", newName);
287 rv = dbMgr->createIndex(indName, idxInfo);
288 if (rv != OK)
290 delete idxInfo;
291 return rv;
293 delete idxInfo;
294 return OK;
298 DbRetVal AlterTblStatement::resolveForModifyColumn()
300 DbRetVal rv = OK;
301 return rv;