*** empty log message ***
[csql.git] / src / sql / DdlStatement.cxx
blob29f279da448e4d87958da4a9373f57a343d70af3
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 <Info.h>
19 #ifndef MMDB
20 #include <TableConfig.h>
21 #endif
22 CreateTblStatement::CreateTblStatement()
24     parsedData = NULL; 
25     dbMgr = NULL; 
28 CreateTblStatement::~CreateTblStatement()
30     tblDef.reset();
32 DbRetVal CreateTblStatement::execute(int &rowsAffected)
34     DbRetVal rv = OK;
35     rv = dbMgr->createTable(tblName, tblDef);
36     if (rv != OK) return rv;
37     if (parsedData->getFieldNameList().size() > 0)
38     {
39         HashIndexInitInfo *idxInfo = new HashIndexInitInfo();
40         strcpy(idxInfo->tableName, tblName);
41         ListIterator iter = parsedData->getFieldNameList().getIterator();
42         FieldName *name = NULL;
43         while (iter.hasElement())
44         {
45             name = (FieldName*)iter.nextElement();
46             idxInfo->list.append(name->fldName);
47         }
48         idxInfo->indType = hashIndex;
49         idxInfo->isPrimary = true;
50         idxInfo->isUnique = true;
51         int bucket = parsedData->getBucketSize();
52         if(bucket!=0)
53             idxInfo->bucketSize = bucket;
54         char indName[IDENTIFIER_LENGTH];
55         sprintf(indName, "%s_idx1_Primary", tblName);
56         rv = dbMgr->createIndex(indName, idxInfo);
57         if (rv != OK)
58         {
59             dbMgr->dropTable(tblName);
60             delete idxInfo;
61             return rv;
62         }
63         delete idxInfo;
64     }
65     if(parsedData->getSecondaryIndexFieldList().size() > 0)
66     {
67         HashIndexInitInfo *idxInfo = new HashIndexInitInfo();
68         strcpy(idxInfo->tableName, tblName);
69         ListIterator iter = parsedData->getSecondaryIndexFieldList().getIterator();
70         FieldInfo *name = NULL;
71         while (iter.hasElement())
72         {
73             name = (FieldInfo*)iter.nextElement();
74             idxInfo->list.append(name->fldName);
75         }
76         idxInfo->indType = treeIndex;
77         idxInfo->isPrimary = true;
78         idxInfo->isUnique = true;
79         char indName[IDENTIFIER_LENGTH];
80         sprintf(indName, "%s_idx_Auto_increment", tblName);
81         rv = dbMgr->createIndex(indName, idxInfo);
82         if (rv != OK)
83         {
84             dbMgr->dropTable(tblName);
85             delete idxInfo;
86             return rv;
87         }
88         delete idxInfo;
89     }
90     if(parsedData->getForeignKeyList().size() > 0)
91     {
92         ForeignKeyInfo *fkInfo=NULL;
93         int i=0;
94         ListIterator iter = parsedData->getForeignKeyList().getIterator();
95         while (iter.hasElement())
96         {
97             fkInfo = (ForeignKeyInfo *)iter.nextElement();
98             strcpy(fkInfo->fkTableName,tblName);
99             char fkName[IDENTIFIER_LENGTH];
100             sprintf(fkName, "%s_FKEY_%d", tblName,++i);
101             rv = dbMgr->createForeignKey(fkName,fkInfo);
102             if (rv != OK)
103             {
104                 dbMgr->dropTable(tblName);
105                 return rv;
106             }
107         } 
109     }
110     return rv;
112 DbRetVal CreateTblStatement::checkForDot(char *name)
114     int i=0;
115     while ( name[i] != '\0')
116     {
117         if (name[i++] == '.') { return ErrSyntaxError; }
118     }
119     return OK;
122 DbRetVal CreateTblStatement::resolve()
124     DbRetVal rv = OK;
125     strcpy(tblName, parsedData->getTableName());
126     rv = checkForDot(tblName);
127     if ( rv!=OK ) 
128     { 
129           printf("Check SQL Syntax: .\n");
130           return  rv;
131     }
132     FieldIterator iter = parsedData->getCreFldList().getIterator();
134     int i = 0;
135     FieldName *name = NULL;
136     ListIterator nIter = parsedData->getFieldNameList().getIterator();
137     while (iter.hasElement())
138     {
139         FieldDef *fDef = iter.nextElement();
140         nIter.reset();
141         while (nIter.hasElement())
142         {
143             name = (FieldName*)nIter.nextElement();
144             if (strcmp(name->fldName, fDef->fldName_) == 0) fDef->isNull_ = true;
145         }
146         rv = checkForDot(fDef->fldName_);
147         if ( rv!=OK )
148         {
149             printf("Check SQL Syntax: .\n");
150             return  rv;
151         }
152         if (fDef->type_ == typeVarchar || fDef->type_ == typeString) {
153             fDef->length_++;
154             //varchar and char require \0 to be stored at the end
155         }
156         /* To check char field and restrict it for the max length 8kb(8000)  */
157         if( (fDef->type_ == typeString) && (fDef->length_ > 8000) ){
158             printError(ErrBadRange,"Char data type length should be less than 8kb(8000).");
159             return ErrBadRange;
160         }
161         //TODO : need a new addField function which can take FieldDef as parameter.
162        if (!fDef->isDefault_ || fDef->isDefault_ && fDef->defaultValueBuf_[0] == '\0')  {
163            i = tblDef.addField(fDef->fldName_, fDef->type_, fDef->length_, 
164                         NULL,fDef->isNull_,fDef->isAutoIncrement_);
165        } else {
166            i = tblDef.addField(fDef->fldName_, fDef->type_, fDef->length_, 
167                         fDef->defaultValueBuf_,fDef->isNull_,fDef->isAutoIncrement_);
168        }
169        if( 0 != i )
170        {
171           printError(ErrUnknown, "Error while adding field");
172           rv = ErrUnknown;
173           break;
174        }
175     }
176     return rv;
178 /////////////////////////////////////
179 DbRetVal CacheTblStatement::resolve()
181     DbRetVal rv = OK;
182 #ifndef MMDB
183     TableConf::config.init();
184     cacheLoader.setConnParam(I_USER, I_PASS);
185     cacheLoader.setTable(parsedData->getTableName());
186     TableConf::config.setTable(parsedData->getTableName());
187     if(parsedData->getHCondFld()){
188         cacheLoader.setCondition(parsedData->getHCondition());// new one
189         TableConf::config.setCondition(parsedData->getHCondition());
190     }
191     if(parsedData->getVCondFld()) {
192         cacheLoader.setFieldListVal(parsedData->getVCondition());
193         TableConf::config.setFieldListVal(parsedData->getVCondition());
194     }
195     if(parsedData->getPkFld()){
196         cacheLoader.setFieldName(parsedData->getIndexName());
197         TableConf::config.setFieldName(parsedData->getIndexName());
198     }
199     if(parsedData->getDSN()){
200         cacheLoader.setDsnName(parsedData->getPKTableName());
201         TableConf::config.setDsnName(parsedData->getPKTableName());
202     }
203     if( !(parsedData->getUnCache()))
204     {
205         rv = TableConf::config.isTableCached(parsedData->getTableName());
206         if(rv == OK){
207            printError(ErrAlready, "Table is already cached,unload table then try");
208            return ErrAlready;
209         }
210     }
211 #endif
212     return OK;
214 DbRetVal CacheTblStatement::execute(int &rowsAffected)
216     DbRetVal rv = OK;
217 #ifndef MMDB
218     if( parsedData->getUnCache())
219     {
220         unsigned int mode = 
221                     TableConf::config.getTableMode(parsedData->getTableName());
222         bool isCached = TableConf::config.isTableCached(mode);
223         if (!isCached) {
224             printError(ErrNotCached, "Table is not Cached");
225             return ErrNotCached;
226         }
227         TableConf::config.removeFromCacheTableFile();
228     } else {
229         rv = cacheLoader.load(!(parsedData->getNoSchema()));
230         if(rv == OK){
231             TableConf::config.addToCacheTableFile(parsedData->getDirect());
232         } else return rv;
233     }
234 #endif
235     return OK;
237 ///////////////////////////////////////
238 CreateIdxStatement::CreateIdxStatement()
240     parsedData = NULL; 
241     dbMgr = NULL; 
244 CreateIdxStatement::~CreateIdxStatement()
249 DbRetVal CreateIdxStatement::execute(int &rowsAffected)
251     DbRetVal rv = OK;
252     if (parsedData->getFieldNameList().size() > 0)
253     {
254         HashIndexInitInfo *idxInfo = new HashIndexInitInfo();
255         strcpy(idxInfo->tableName, parsedData->getTableName());
256         ListIterator iter = parsedData->getFieldNameList().getIterator();
257         FieldName *name = NULL;
258         while (iter.hasElement())
259         {
260             name = (FieldName*)iter.nextElement();
261             idxInfo->list.append(name->fldName);
262         }
263         idxInfo->indType = parsedData->getIndexType();
264         idxInfo->isPrimary = parsedData->getPrimary();
265         idxInfo->isUnique = parsedData->getUnique();
266         int bucket = parsedData->getBucketSize();
267         if(bucket!=0)
268             idxInfo->bucketSize = bucket;
269         rv = dbMgr->createIndex(parsedData->getIndexName(), idxInfo);
270         delete idxInfo;
271     }
272     if (rv == OK) dbMgr->sendSignal(SIGCSQL1);
273     return rv;
276 // function for not to drop cached table
277 DbRetVal isTableCached(char *tabName) // function added by :Jitendra
279        
280     DbRetVal rv =OK;
281     FILE *fp;
282     if (!Conf::config.useCache()) return OK;
283     fp = fopen(Conf::config.getTableConfigFile(),"r");
284     if(fp==NULL) return OK;
285     char tablename[IDENTIFIER_LENGTH]; tablename[0] = '\0';
286     char condition[IDENTIFIER_LENGTH]; condition[0]='\0';
287     char fieldname[IDENTIFIER_LENGTH]; fieldname[0]='\0';
288     char field[IDENTIFIER_LENGTH];  field[0]='\0';
289     char dsnName[IDENTIFIER_LENGTH]; dsnName[0]='\0';
290     int mode;
291     while(!feof(fp))
292     {
293         fscanf(fp,"%d %s %s %s %s %s\n",&mode,tablename,fieldname,condition,field,dsnName);
294         if(strcmp(tablename,tabName) ==0){
295         fclose(fp);
296         return ErrNoPrivilege;}
297     }
298     fclose(fp);
299     return rv;
300 }      
302 DbRetVal DropTblStatement::execute(int &rowsAffected)
304     DbRetVal rv = OK; // newly added
305     char *tab;
306     tab = parsedData->getTableName();
308     DatabaseManagerImpl *dmgr = (DatabaseManagerImpl *)dbMgr;
309     IsolationLevel iso = dmgr->txnMgr()->getIsoLevel();
310     rv = dmgr->txnMgr()->rollback(dmgr->lockMgr());
311     rv = dmgr->txnMgr()->startTransaction(dmgr->lockMgr(),iso);    
312 #ifndef MMDB    
313     int mode = TableConf::config.getTableMode(tab);
314 //    rv = isTableCached(tab);
315     if (mode != 0 && mode < 8) {
316             printf("Cached table '%s' cannot be dropped.\n", tab);
317         printf("uncache the table by 'cachetable -t %s -u' and drop.\n", tab);
318             printError(ErrNoPrivilege, "Cached table '%s' cannot be dropped.", tab);
319         return ErrNoPrivilege;
320     } 
321     else if (mode == 8) {
322         printf("Replicated table '%s' cannot be dropped.\n", tab);
323         printf("Unreplicate the table by 'repltable -t %s -u' and drop.\n", tab);
324         printError(ErrNoPrivilege, "Replicated table '%s' cannot be dropped.", tab);
325         return ErrNoPrivilege;
326     }
327     else if (mode > 8) {
328         printf("Table %s is cached and replicated. Cannot be dropped.\n", tab);
329         printf("Uncache the table by 'cachetable -t %s -u'.\n", tab);
330         printf("Unreplicated the table by 'repltable -t %s -u' and drop.\n", tab);   
331         printError(ErrNoPrivilege, "Table %s is cached and replicated. Cannot be dropped.", tab);
332         return ErrNoPrivilege;
333     }
334 #endif
335     rv = dbMgr->dropTable(parsedData->getTableName());
336     if (rv == OK) dbMgr->sendSignal(SIGCSQL1);
337     return rv;
340 DbRetVal DropIdxStatement::execute(int &rowsAffected)
342     DbRetVal rv = OK;
343     DatabaseManagerImpl *dmgr = (DatabaseManagerImpl *)dbMgr;
344     IsolationLevel iso = dmgr->txnMgr()->getIsoLevel();
345     rv = dmgr->txnMgr()->rollback(dmgr->lockMgr());
346     rv = dmgr->txnMgr()->startTransaction(dmgr->lockMgr(),iso);
347     rv = dmgr->dropIndex(parsedData->getIndexName());
348     if (rv == OK) dbMgr->sendSignal(SIGCSQL1);
349     return rv;
352 //================== Truncate Table Statement ===============
355 DbRetVal TruncateTblStatement::execute(int &rowsAffected)
357     DbRetVal rv = OK;
358     table->setCondition(NULL);
359     IsolationLevel level = ((DatabaseManagerImpl*)dbMgr)->txnMgr()->getIsoLevel();
360     rv=((DatabaseManagerImpl*)dbMgr)->txnMgr()->commit(((DatabaseManagerImpl*)dbMgr)->lockMgr());
361     if (rv != OK) return rv;
362     rv=((DatabaseManagerImpl*)dbMgr)->txnMgr()->startTransaction(((DatabaseManagerImpl*)dbMgr)->lockMgr(),level);
363     if (rv != OK) return rv;
365     rv = table->execute();
366     if (rv != OK) return rv;
367     rowsAffected = 0;
368     table->setLoading(true);
369     void *tuple;
370     while(true)
371     {
372         tuple = (char*)table->fetchNoBind(rv);
373         if (rv != OK) break;
374         if (tuple == NULL) {break;}
375         rv = table->deleteTuple();
376         if (rv != OK) break;
377         rowsAffected++;
378     }
379     table->closeScan();
380     return rv;
382 DbRetVal TruncateTblStatement::resolve()
384    DbRetVal rv = OK;
385    table = dbMgr->openTable(parsedData->getTableName());
386     if (table == NULL)
387     {
388         printError(ErrNotExists, "Unable to open the table:Table not exists");
389         return ErrNotExists;
390     }
391     return rv;
398 //================== Compact Table Statement===================
399 DbRetVal CompactTblStatement::resolve()
401     DbRetVal rv = OK;
402     table = dbMgr->openTable(parsedData->getTableName());
403     if (table == NULL)
404     {
405         printError(ErrNotExists, "Unable to open the table:Table not exists");
406         return ErrNotExists;
407     }
408     return OK;
410 DbRetVal CompactTblStatement::execute(int &rowsAffected)
412     DbRetVal rv = OK;
413     rv = table->compact();
414     dbMgr->closeTable(table);
415     return rv;
417 DbRetVal UserTblStatement::resolve()
419     uType = parsedData->getUserType();
420     if( uType == CREATEUSER || uType == DROPUSER || (uType == ALTERUSER && strcmp(userName,parsedData->getUserName())!=0))
421     {
422        if(strcmp(userName,"root")!=0)
423        {
424            printError(ErrNoPrivilege,"Permission Denied. Login as root");
425            return ErrNoPrivilege;
426        }else if(uType == DROPUSER && strcmp(parsedData->getUserName(),"root")==0)
427        {
428             printError(ErrNoPrivilege,"Permission Denied. root user cannot be deleted");
429             return ErrNoPrivilege;
430        }
431     }
432     return OK;
434 DbRetVal UserTblStatement::execute(int &rowsAffected)
436     DbRetVal rv = OK;
437     if( uType == CREATEUSER){
438        rv =(DbRetVal) usrMgr->createUser(parsedData->getUserName(), parsedData->getPassWord());
439     }else if(uType == DROPUSER){
440        rv =(DbRetVal) usrMgr->deleteUser(parsedData->getUserName());
441     }else{
442        rv =(DbRetVal) usrMgr->changePassword(parsedData->getUserName(), parsedData->getPassWord());
443     }
444     return rv;