From 460f415f3ae8696b45a8df7e2365654e2bb1efed Mon Sep 17 00:00:00 2001 From: prabatuty Date: Thu, 2 Jun 2011 02:48:55 +0000 Subject: [PATCH] code reorg --- src/storage/DbMgrFkImpl.cxx | 171 +++++++++ src/storage/DbMgrIndexImpl.cxx | 769 +++++++++++++++++++++++++++++++++++++++++ src/storage/DbMgrTableImpl.cxx | 520 ++++++++++++++++++++++++++++ src/storage/Makefile.am | 3 +- 4 files changed, 1462 insertions(+), 1 deletion(-) create mode 100644 src/storage/DbMgrFkImpl.cxx create mode 100644 src/storage/DbMgrIndexImpl.cxx create mode 100644 src/storage/DbMgrTableImpl.cxx diff --git a/src/storage/DbMgrFkImpl.cxx b/src/storage/DbMgrFkImpl.cxx new file mode 100644 index 00000000..21acaae4 --- /dev/null +++ b/src/storage/DbMgrFkImpl.cxx @@ -0,0 +1,171 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DbRetVal DatabaseManagerImpl::createForeignKey(char *fKName,ForeignKeyInfo *info) +{ + DbRetVal rv = OK; + int totFkFlds = info->fkFldList.size(); + int totPkFlds = info->pkFldList.size(); + if (totFkFlds==0 && totPkFlds==0) { + printError(ErrBadCall, "No Field name specified"); + return ErrBadCall; + } + void *tptr =NULL; + void *chunk = NULL; + void *vcchunk = NULL; + rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(info->fkTableName, chunk, tptr, vcchunk); + if (NULL == tptr) + { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrNotExists, "Table does not exist %s", info->fkTableName); + return ErrNotExists; + } + char **fptr = new char* [totFkFlds]; + CatalogTableFIELD cField(systemDatabase_); + rv = cField.getFieldPtrs(info->fkFldList, tptr, fptr); + if (OK != rv) + { + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + if (rv != ErrBadCall) { + printError(ErrNotExists, "Field does not exist"); + return ErrNotExists; + } + } + void *tPkptr =NULL; + void *chunkPk = NULL; + void *vcchunkPk = NULL; + CatalogTableTABLE c2Table(systemDatabase_); + c2Table.getChunkAndTblPtr(info->pkTableName, chunkPk, tPkptr, vcchunkPk); + if (NULL == tPkptr) + { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrNotExists, "Table does not exist %s", info->pkTableName); + return ErrNotExists; + } + char **fPkptr = new char* [totPkFlds]; + CatalogTableFIELD c2Field(systemDatabase_); + rv = c2Field.getFieldPtrs(info->pkFldList, tPkptr, fPkptr); + if (OK != rv) + { + delete[] fptr; + delete[] fPkptr; + systemDatabase_->releaseCheckpointMutex(); + if (rv != ErrBadCall) { + printError(ErrNotExists, "Field does not exist"); + return ErrNotExists; + } + } + //Create New chunkdatanode + CatalogTableFK cFK(systemDatabase_); + rv = cFK.insert(fKName, tptr, tPkptr);//TODO + if (OK != rv) + { + delete[] fptr; + delete[] fPkptr; + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Catalog table updation failed in CFK table"); + return ErrSysInternal; + } + + CatalogTableFKFIELD cFKField(systemDatabase_); + rv = cFKField.insert(fKName,fptr,fPkptr,totFkFlds); + if (OK != rv) + { + delete[] fptr; + delete[] fPkptr; + cFK.remove(tptr); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Catalog table updation failed in CFKFIELD table"); + return ErrSysInternal; + } + systemDatabase_->releaseCheckpointMutex(); + delete[] fptr; + delete[] fPkptr; + return rv; +} + +DbRetVal DatabaseManagerImpl::dropForeignKey(void *tptr,bool trylock) +{ + DbRetVal rv = OK; + if(trylock){ + rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + } + void *fkChunk=NULL; + CatalogTableFK cFK(systemDatabase_); + int total = cFK.getNoOfPkTable(tptr); + //printDebug(DM_TEST,"total fk chunk %d",total); + for (int i=0;i< total; i++) + { + fkChunk = cFK.getFkCTable(tptr); + if(NULL==fkChunk) + { + if(trylock){ + systemDatabase_->releaseCheckpointMutex(); + } + printError(ErrSysInternal, "Catalog table not finds CFKFIELD table"); + return ErrSysInternal; + } + CatalogTableFKFIELD cFKField(systemDatabase_); + rv = cFKField.remove(fkChunk); + if (OK != rv) + { + if(trylock){ + systemDatabase_->releaseCheckpointMutex(); + } + printError(ErrSysInternal, "Catalog table updation failed in CFKFIELD table"); + return ErrSysInternal; + } + rv =cFK.remove(fkChunk); + if (OK != rv) + { + if(trylock){ + systemDatabase_->releaseCheckpointMutex(); + } + printError(ErrSysInternal, "Catalog table updation failed for INDEX table"); + return ErrSysInternal; + } + } + if(trylock){ + systemDatabase_->releaseCheckpointMutex(); + } + return rv; +} diff --git a/src/storage/DbMgrIndexImpl.cxx b/src/storage/DbMgrIndexImpl.cxx new file mode 100644 index 00000000..98b80419 --- /dev/null +++ b/src/storage/DbMgrIndexImpl.cxx @@ -0,0 +1,769 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DbRetVal DatabaseManagerImpl::renameIndex(const char *oldName,const char *newName) +{ + void *chunk = NULL; + DbRetVal rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex for rename table"); + return ErrSysInternal; + } + CatalogTableTABLE cTable(systemDatabase_); + rv = cTable.renameIndex(oldName,newName); + if (OK != rv) { + printError(ErrSysInternal, "Unable to rename table"); + systemDatabase_->releaseCheckpointMutex(); + return ErrSysInternal; + } + systemDatabase_->releaseCheckpointMutex(); + return OK; +} + +DbRetVal DatabaseManagerImpl::createIndex(const char *indName, IndexInitInfo *info) +{ + DbRetVal rv = OK; + if (!info->isUnique && info->isPrimary) + { + printError(ErrBadCall, "Primary key cannot be non unique\n"); + return ErrBadCall; + } + if (!Util::isIdentifier((char*)indName)) { + printError(ErrBadArg, "Invalid character for index name"); + return ErrBadArg; + } + + if (info->indType == hashIndex) + { + //Assumes info is of type HashIndexInitInfo + HashIndexInitInfo *hInfo = (HashIndexInitInfo*) info; + rv = createHashIndex(indName, info->tableName, info->list, hInfo->bucketSize, + info->isUnique, info->isPrimary); + } + else if (info->indType == treeIndex) + { + HashIndexInitInfo *hInfo = (HashIndexInitInfo*) info; + rv = createTreeIndex(indName, info->tableName, info->list, + hInfo->bucketSize, info->isUnique, info->isPrimary); + } + else if (info->indType == trieIndex) + { + HashIndexInitInfo *hInfo = (HashIndexInitInfo*) info; + rv = createTrieIndex(indName, info->tableName, info->list, + info->isUnique, info->isPrimary); + + }else { + printError(ErrBadCall, "Index type not supported\n"); + return ErrBadCall; + } + return rv; +} + + +//-1 -> Table does not exists +//-2 -> Field does not exists +//-3 -> bucketSize is not valid +DbRetVal DatabaseManagerImpl::createHashIndex(const char *indName, const char *tblName, + FieldNameList &fldList, int bucketSize, bool isUnique, bool isPrimary) +{ + //validate the bucket size + if (bucketSize < 100 || bucketSize > 200000) + { + printError(ErrBadRange, "Index Bucket size %d not in range 100-200000", + bucketSize); + return ErrBadRange; + } + int totFlds = fldList.size(); + if (totFlds == 0) + { + printError(ErrBadCall, "No Field name specified"); + return ErrBadCall; + } + void *tptr =NULL; + void *chunk = NULL; + void *vcchunk = NULL; + DbRetVal rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + + //check whether table exists + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(tblName, chunk, tptr, vcchunk); + if (NULL == tptr) + { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrNotExists, "Table does not exist %s", tblName); + return ErrNotExists; + } + + //check whether field exists + char **fptr = new char* [totFlds]; + CatalogTableFIELD cField(systemDatabase_); + rv = cField.getFieldPtrs(fldList, tptr, fptr); + if (OK != rv) + { + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + //TODO::check test cases of dbapi/Index, they give wrong results + //if (rv == ErrBadCall) { + //// if (isPrimary) printError(ErrBadCall, "Field can have NULL values"); + //} else { + //printError(ErrNotExists, "Field does not exist"); + //} + //return ErrBadCall; + if (rv != ErrBadCall) { + printError(ErrNotExists, "Field does not exist"); + return ErrNotExists; + } + } + for (int i=0; i type_ == typeFloat || fInfo->type_ == typeDouble || fInfo->type_ == typeTimeStamp) + { + printError(ErrBadArg, "HashIndex cannot be created for float or double or timestamp type"); + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + return ErrBadArg; + } + if (!fInfo->isNull_ && isPrimary ) + { + printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint"); + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + return ErrBadArg; + } + if(isPrimary){fInfo->isPrimary_=true;fInfo->isUnique_=true;} + if(isUnique){fInfo->isUnique_=true;} + } + //create chunk to store the meta data of the index created + //for latches and bucket pointers + printDebug(DM_HashIndex, "Creating chunk for storing hash buckets of size %d\n", + bucketSize * sizeof(Bucket)); + Chunk* chunkInfo = createUserChunk(bucketSize * sizeof(Bucket)); + if (NULL == chunkInfo) + { + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Unable to create chunk"); + return ErrSysInternal; + } + chunkInfo->setChunkName(indName); + //create memory for holding the bucket pointers + void *buckets = chunkInfo->allocate(db_, &rv); + if (NULL == buckets) + { + delete[] fptr; + deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(rv, "Unable to allocate memory for bucket"); + return rv; + } + Bucket *buck = (Bucket*) buckets; + initHashBuckets(buck, bucketSize); + + //create chunk to store the hash index nodes + Chunk* hChunk = createUserChunk(sizeof(IndexNode)); + if (NULL == hChunk) + { + delete[] fptr; + deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Unable to create chunk for storing hash index nodes"); + return ErrSysInternal; + } + + hChunk->setChunkName(indName); + //add row to INDEX + void *tupleptr = NULL; + CatalogTableINDEX cIndex(systemDatabase_); + rv = cIndex.insert(indName, tptr, fldList.size(), isUnique, + chunkInfo, bucketSize, hChunk, tupleptr); + if (OK != rv) + { + delete[] fptr; + deleteUserChunk(hChunk); + deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Catalog table updation failed in INDEX table"); + return ErrSysInternal; + } + //add rows to INDEXFIELD + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + rv = cIndexField.insert(fldList, tupleptr, tptr, fptr); + + if (OK != rv) + { + delete[] fptr; + cIndex.remove(indName, (void *&)chunkInfo, (void *&)hChunk, (void *&)tupleptr); + deleteUserChunk(hChunk); + deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Catalog table updation failed in INDEXFIELD table"); + return ErrSysInternal; + } + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + + //TODO:: Take table lock + + // Following code is written by Kishor Amballi + TableImpl *tbl = (TableImpl *) openTable(tblName); + if (NULL == tbl) { + printError(ErrSysInternal, "Unable to open table %s", tblName); + return ErrSysInternal; + } + if (! tbl->numTuples()) { + printDebug(DM_Database, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName, tblName, buckets); + logFinest(Conf::logger, "Creating HashIndex %s on %s with bucket size %d", indName, tblName, buckets); + closeTable(tbl); + return OK; + } + HashIndexInfo *indxInfo = NULL; + int i = 0; + for (i = 0; i < tbl->numIndexes_; i++) { + if(((HashIndexInfo *)tbl->idxInfo[i])->indexPtr == tupleptr) { + indxInfo = (HashIndexInfo *) tbl->idxInfo[i]; + break; + } + } + void *recPtr = NULL; + ChunkIterator chIter = ((Chunk *)chunk)->getIterator(); + tbl->setLoading(true); + while ((recPtr = chIter.nextElement()) != NULL) { + rv = tbl->insertIndexNode(*tbl->trans, tupleptr, indxInfo, recPtr); + if (rv == ErrUnique) { + closeTable(tbl); + dropIndex(indName); + return rv; + } + } + closeTable(tbl); + printDebug(DM_Database, "Creating Hash Index Name:%s tblname:%s buckets:%x", indName, tblName, buckets); + logFinest(Conf::logger, "Creating HashIndex %s on %s with bucket size %d", indName, tblName, buckets); + return OK; +} + + +DbRetVal DatabaseManagerImpl::createTreeIndex(const char *indName, const char *tblName, + FieldNameList &fldList, int nodeSize, bool isUnique, bool isPrimary) +{ + if (nodeSize < 20 || nodeSize > 20000) + { + printError(ErrBadRange,"Tree Index Node size %d not in range 20-20000", + nodeSize); + return ErrBadRange; + } + int totFlds = fldList.size(); + if (totFlds == 0) { + printError(ErrBadCall, "No Field name specified"); + return ErrBadCall; + }else if (totFlds != 1) { + printError(ErrBadCall, "Composite index not supported for Tree"); + return ErrBadCall; + } + void *tptr =NULL; + void *chunk = NULL; + void *vcchunk = NULL; + DbRetVal rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + //check whether table exists + + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(tblName, chunk, tptr, vcchunk); + if (NULL == tptr) + { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrNotExists, "Table does not exist %s", tblName); + return ErrNotExists; + } + char **fptr = new char* [totFlds]; + CatalogTableFIELD cField(systemDatabase_); + rv = cField.getFieldPtrs(fldList, tptr, fptr); + if (OK != rv) + { + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + if (rv != ErrBadCall) { + printError(ErrNotExists, "Field does not exist"); + return ErrNotExists; + } + } + for (int i=0; i isNull_ && isPrimary ) + { + printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint"); + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + return ErrBadArg; + } + if (fInfo->type_ == typeVarchar) + { + printError(ErrBadArg, "Tree Index not supported for varchar type. Use char data type instead."); + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + return ErrBadArg; + } + + } + int chunkSize = sizeof(TreeNode)+(nodeSize * sizeof(void*)); + printDebug(DM_HashIndex, "Creating chunk for storing tree nodes of size %d\n", chunkSize); + + Chunk* chunkInfo = createUserChunk(chunkSize); + if (NULL == chunkInfo) + { + delete[] fptr; + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Unable to create chunk"); + return ErrSysInternal; + } + + + void *tupleptr = NULL; + + CatalogTableINDEX cIndex(systemDatabase_); + rv = cIndex.insert(indName, tptr, fldList.size(), isUnique, + chunkInfo, nodeSize, NULL, tupleptr); + if (OK != rv) + { + delete[] fptr; + deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Catalog table updation failed in INDEX table"); + return ErrSysInternal; + } + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + rv = cIndexField.insert(fldList, tupleptr, tptr, fptr); + + if (OK != rv) + { + delete[] fptr; + void *hChunk = NULL; + cIndex.remove(indName, (void *&)chunkInfo, (void *&)hChunk, (void *&)tupleptr); + deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Catalog table updation failed in INDEXFIELD table"); + return ErrSysInternal; + } + delete[] fptr; + rv = createIndexNodeForRecords(tblName, tupleptr, chunk); + if (rv != OK) + { + dropIndex(indName); + systemDatabase_->releaseCheckpointMutex(); + return rv; + } + systemDatabase_->releaseCheckpointMutex(); + logFinest(Conf::logger, "Creating TreeIndex %s on %s rv:%d", + indName, tblName, rv); + return OK; +} +DbRetVal DatabaseManagerImpl::createIndexNodeForRecords(const char* tblName, + void *tupleptr, void *chunk) +{ + //TODO::if tuples already present in this table, then create tree index ' + //nodes + TableImpl *tbl = (TableImpl *) openTable(tblName); + if (NULL == tbl) { + printError(ErrSysInternal, "Unable to open table %s", tblName); + return ErrSysInternal; + } + if (! tbl->numTuples()) { + closeTable(tbl); + return OK; + } + HashIndexInfo *indxInfo = NULL; + int i = 0; + for (i = 0; i < tbl->numIndexes_; i++) { + if(((HashIndexInfo *)tbl->idxInfo[i])->indexPtr == tupleptr) { + indxInfo = (HashIndexInfo *) tbl->idxInfo[i]; + break; + } + } + void *recPtr = NULL; + ChunkIterator chIter = ((Chunk *)chunk)->getIterator(); + tbl->setLoading(true); + DbRetVal rv = OK; + while ((recPtr = chIter.nextElement()) != NULL) { + rv = tbl->insertIndexNode(*tbl->trans, tupleptr, indxInfo, recPtr); + if (rv == ErrUnique) { + closeTable(tbl); + return rv; + } + } + closeTable(tbl); + return OK; +} + +DbRetVal DatabaseManagerImpl::createTrieIndex(const char *indName, const char *tblName, + FieldNameList &fldList, bool isUnique, bool isPrimary) +{ + int totFlds = fldList.size(); + void *tptr =NULL; + char **fptr = new char* [totFlds]; + DbRetVal rv = validateIndex(tblName, fldList, &tptr, &fptr, isPrimary); + if (OK != rv) + { + delete[] fptr; + return rv; + } + rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + + //below statements are actually setting values in the catalog table + //thats why mutex is taken before this stmt. Do not change the order + CFIELD* fInfo = (CFIELD*)fptr[0]; + if(isPrimary){fInfo->isPrimary_=true;fInfo->isUnique_=true;} + if(isUnique){fInfo->isUnique_=true;} + + printDebug(DM_TrieIndex, "Creating chunk for storing trie nodes\n" ); + Chunk* chunkInfo = createUserChunk(sizeof(TrieNode)); + + //chunk to store the linked list of trie values + Chunk* hChunk = createUserChunk(sizeof(IndexNode)); + if (NULL == chunkInfo || NULL == hChunk) + { + delete[] fptr; + if (chunkInfo) deleteUserChunk(chunkInfo); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Unable to create trie node chunk"); + return ErrSysInternal; + } + chunkInfo->setChunkName(indName); + hChunk->setChunkName(indName); + void *tupleptr = NULL; + rv = updateIndexCatalogTables(indName,tptr, fptr, fldList, isUnique, + chunkInfo, hChunk , tupleptr); + delete[] fptr; + if (OK != rv) { + printError(ErrSysInternal, "Catalog table updation failed"); + deleteUserChunk(chunkInfo); + deleteUserChunk(hChunk); + systemDatabase_->releaseCheckpointMutex(); + return rv; + } + + void *chunk = NULL; + void *vcchunk = NULL; + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(tblName, chunk, tptr, vcchunk); + //create index nodes if records already exist in the table + rv = createIndexNodeForRecords(tblName, tupleptr, chunk); + if (rv != OK) + { + dropIndex(indName); + systemDatabase_->releaseCheckpointMutex(); + return rv; + } + systemDatabase_->releaseCheckpointMutex(); + logFinest(Conf::logger, "Creating TrieIndex %s on %s rv:%d", + indName, tblName, rv); + return OK; +} +DbRetVal DatabaseManagerImpl::validateIndex(const char *tblName, + FieldNameList &fldList, void **tptr, char ***fptr, + bool isPrimary) +{ + int totFlds = fldList.size(); + if (totFlds != 1) + { + printError(ErrBadCall, "No Field name specified or composite fields specified"); + return ErrBadCall; + } + void *chunk = NULL; + void *vcchunk = NULL; + //check whether table exists + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(tblName, chunk, *tptr, vcchunk); + if (NULL == tptr) + { + printError(ErrNotExists, "Table does not exist %s", tblName); + return ErrNotExists; + } + + //check whether field exists + CatalogTableFIELD cField(systemDatabase_); + DbRetVal rv = cField.getFieldPtrs(fldList, *tptr, *fptr); + if (OK != rv) + { + if (rv != ErrBadCall) { + printError(ErrNotExists, "Field does not exist"); + return ErrNotExists; + } + } + CFIELD* fInfo = (CFIELD*)*fptr[0]; + if (!(fInfo->type_ == typeInt || fInfo->type_ == typeLongLong || fInfo->type_ == typeString || fInfo->type_ == typeVarchar)) + { + printError(ErrBadArg, "Trie Index cannot be created for float or double or timestamp type"); + return ErrBadArg; + } + if (!fInfo->isNull_ && isPrimary ) + { + printError(ErrBadArg, "Primary Index cannot be created on field without NOTNULL constraint"); + return ErrBadArg; + } + + return OK; +} + +DbRetVal DatabaseManagerImpl::updateIndexCatalogTables(const char *indName, + void *tptr, char **fptr, FieldNameList &fldList, + bool isUnique, Chunk* chunkInfo, Chunk* hChunk, + void *&tupleptr ) +{ + //void *tupleptr = NULL; + CatalogTableINDEX cIndex(systemDatabase_); + DbRetVal rv = cIndex.insert(indName, tptr, fldList.size(), isUnique, + chunkInfo, 0, hChunk, tupleptr); + if (OK != rv) + { + printError(ErrSysInternal, "Catalog table updation failed in INDEX table"); + return ErrSysInternal; + } + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + rv = cIndexField.insert(fldList, tupleptr, tptr, fptr); + if (OK != rv) + { + //rollback the previous operation + cIndex.remove(indName, (void *&)chunkInfo, (void *&)hChunk, (void *&)tupleptr); + printError(ErrSysInternal, "Catalog table updation failed in INDEXFIELD table"); + return ErrSysInternal; + } + return rv; +} + +DbRetVal DatabaseManagerImpl::removeIndexCatalogTables(const char *name, void *&chunk, void *&hchunk, void *&tptr) +{ + //remove the entry in INDEX + CatalogTableINDEX cIndex(systemDatabase_); + DbRetVal rv = cIndex.remove(name, chunk, hchunk, tptr); + if (OK != rv) + { + printError(ErrSysInternal, "Catalog table updation failed for INDEX table"); + return ErrSysInternal; + } + printDebug(DM_Database, "Removing from INDEX %s",name); + //remove the entries in the INDEXFIELD table + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + rv = cIndexField.remove(tptr); + if (OK != rv) + { + printError(ErrSysInternal, "Catalog table updation failed for INDEX table"); + return ErrSysInternal; + } + printDebug(DM_Database, "Removing from INDEXFIELD %s",name); + return OK; +} +DbRetVal DatabaseManagerImpl::removeIndexChunks(void* chunk, void* hchunk, IndexType iType) +{ + DbRetVal rv = deleteUserChunk((Chunk*)chunk); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to delete the index chunk"); + return ErrSysInternal; + } + //delete the index hash node chunk + if (iType == hashIndex || iType == trieIndex) { + rv = deleteUserChunk((Chunk*)hchunk); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to delete the index hash node chunk"); + return ErrSysInternal; + } + } + return OK; +} + +void DatabaseManagerImpl::initHashBuckets(Bucket *buck, int bucketSize) +{ + os::memset((void*)buck, 0, bucketSize * sizeof(Bucket)); + char mutName[IDENTIFIER_LENGTH]; + for (int i=0; i < bucketSize ; i++) + { + sprintf(mutName, "BKT:%d",i); + buck[i].mutex_.init(mutName); + } + return; +} + +DbRetVal DatabaseManagerImpl::dropIndex(const char *name) +{ + return dropIndexInt(name, true); +} + +DbRetVal DatabaseManagerImpl::dropIndexInt(const char *name, bool takeLock) +{ + DbRetVal rv = OK; + void *chunk = NULL, *hchunk = NULL; + void *tptr =NULL; + int ret = 0; + if (takeLock) { + rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) + { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + } + rv = removeIndexCatalogTables(name, chunk, hchunk, tptr); + if (OK != rv) + { + if (takeLock) systemDatabase_->releaseCheckpointMutex(); + return rv; + } + + CINDEX *iptr = (CINDEX*)tptr; + rv = removeIndexChunks(chunk, hchunk, iptr->indexType_); + if (OK != rv) + { + if (takeLock) systemDatabase_->releaseCheckpointMutex(); + return rv; + } + if (takeLock) systemDatabase_->releaseCheckpointMutex(); + + printDebug(DM_Database, "Dropped index %s",name); + logFinest(Conf::logger, "Deleted Index %s", name); + return OK; +} + +void DatabaseManagerImpl::printTreeIndexNodeInfo(char *name, bool flag) +{ + CatalogTableINDEX cIndex(systemDatabase_); + DbRetVal rv = OK; + void *chunk = NULL, *hchunk = NULL; + void *tptr =NULL; + rv = cIndex.get(name, chunk, hchunk, tptr); + if (OK != rv) return; + IndexType iType = CatalogTableINDEX::getType(tptr); + if (treeIndex != iType) + { + printf("%s is not a tree index\n "); + return; + } + Chunk *ch = (Chunk*) chunk; + if(flag){ if(hchunk)((TreeNode*) hchunk)->displayAll(); } + else { + int offset = CatalogTableINDEX::getOffsetOfFirstField(tptr); + //if(typeInt != offset) { printf("%s is not on Integer Type Field. To see info Index should be on integer type field. \n "); return;} + if(hchunk) ((TreeNode*) hchunk)->displayAll(offset); + } +} +DbRetVal DatabaseManagerImpl::printIndexDebugInfo(char *name) +{ + CatalogTableINDEX cIndex(systemDatabase_); + DbRetVal rv = OK; + void *chunk = NULL, *hchunk = NULL; + void *tptr =NULL; + rv = cIndex.get(name, chunk, hchunk, tptr); + if (OK != rv) return rv; + IndexType iType = CatalogTableINDEX::getType(tptr); + if(hashIndex == iType) { + } + else if (treeIndex == iType) { + CINDEX *iptr = (CINDEX*)tptr; + TreeNode *start = (TreeNode*) iptr->hashNodeChunk_; + start->displayAll(0); + } + else if (trieIndex == iType) { + ChunkIterator citer = CatalogTableINDEX::getIterator(tptr); + TrieNode* start = (TrieNode*)citer.nextElement(); + if(start) TrieIndex::displayAll(start); + } + else + printf("Unknown Index\n"); + + +} +DbRetVal DatabaseManagerImpl::printIndexInfo(char *name) +{ + CatalogTableINDEX cIndex(systemDatabase_); + DbRetVal rv = OK; + void *chunk = NULL, *hchunk = NULL; + void *tptr =NULL; + rv = cIndex.get(name, chunk, hchunk, tptr); + if (OK != rv) return rv; + printf(" %s \n", name); + printf(" %d \n", CatalogTableINDEX::getUnique(tptr)); + IndexType iType = CatalogTableINDEX::getType(tptr); + if(hashIndex == iType) + printf(" Hash Index \n"); + else if (treeIndex == iType) + printf(" Tree Index \n"); + else if (trieIndex == iType) + printf(" Trie Index \n"); + else + printf(" Unknown Index \n"); + + Chunk *ch = (Chunk*) chunk; + printf("\n"); + printf(" %d \n", ch->totalPages()); + printf(" %d \n", CatalogTableINDEX::getNoOfBuckets(tptr)); + printf("\n"); + printf("\n"); + if(hashIndex == iType){ + ch = (Chunk*) hchunk; + printf(" %d \n", ch->totalPages()); + printf(" %d \n", ch->getTotalDataNodes()); + } else if (treeIndex == iType) { + printf(" %d \n", ch->getTotalDataNodes()); + if(hchunk) + printf(" %lld \n",((TreeNode*) hchunk)->getTotalElements()); + else + printf(" 0 \n"); + } else if (trieIndex == iType) + { + printf(" \n"); + printf(" %d \n", ch->totalPages()); + printf(" %d \n", ch->getTotalDataNodes()); + printf(" \n \n"); + ch = (Chunk*) hchunk; + printf(" %d \n", ch->totalPages()); + printf(" %d \n", ch->getTotalDataNodes()); + printf(" \n"); + } else + { + printf("Unknown Index type\n"); + } + printf("\n"); + return OK; +} diff --git a/src/storage/DbMgrTableImpl.cxx b/src/storage/DbMgrTableImpl.cxx new file mode 100644 index 00000000..30b5ccc8 --- /dev/null +++ b/src/storage/DbMgrTableImpl.cxx @@ -0,0 +1,520 @@ +/*************************************************************************** + * Copyright (C) 2007 by www.databasecache.com * + * Contact: praba_tuty@databasecache.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//-1 -> Unable to create chunk. No memory +//-2 -> Unable to update the catalog tables +DbRetVal DatabaseManagerImpl::createTable(const char *name, TableDef &def) +{ + DbRetVal rv = OK; + if (!Util::isIdentifier((char*)name)) { + printError(ErrBadArg, "Invalid character for index name"); + return ErrBadArg; + } + int fldCount = def.getFieldCount(); + if(0==fldCount) + { + printError(ErrNotExists,"Table can't be created without Field"); + return ErrNotExists; + } + + //If total field count is within 32, then 1 integer is used to store all + // null information, if it is more then 1 char is used to store null + // information of each field + //This is to done to reduce cpu cycles for small tables + int addSize = 0; + if (fldCount <= 32) addSize = 4; else addSize = os::align(fldCount); + size_t sizeofTuple = os::alignLong(def.getTupleSize()+addSize); + rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv ) { + printError(rv, "Unable to get Database mutex"); + return rv; + } + + void *tptr =NULL; + void *chunk = NULL; + void *vcchunk = NULL; + + //check whether table already exists + CatalogTableTABLE cTable(systemDatabase_); + cTable.getChunkAndTblPtr(name, chunk, tptr, vcchunk); + if (NULL != tptr) + { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrAlready, "Table %s already exists", name); + return ErrAlready; + } + + //create a chunk to store the tuples + Chunk *ptr = createUserChunk(sizeofTuple); + if (NULL == ptr) + { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrNoResource, "Unable to create user chunk"); + return ErrNoResource; + } + printDebug(DM_Database,"Created UserChunk:%x", ptr); + ptr->setChunkName(name); + //add row to TABLE + int tblID = ((Chunk*)ptr)->getChunkID(); + + //check whether varchar is present in table + FieldIterator fiter = def.getFieldIterator(); + bool isVarcharPresent = def.isVarcharPresentInSchema(fiter); + Chunk *vcptr = NULL; + if (isVarcharPresent) { + //creat chunk to store varchar values + vcptr = createUserChunk(); + if (NULL == vcptr) + { + deleteUserChunk(ptr); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrNoResource, "Unable to create user chunk for varchar"); + return ErrNoResource; + } + printDebug(DM_Database,"Created UserChunk for Varchar:%x", vcptr); + vcptr->setChunkName(name); + } + rv = cTable.insert(name, tblID, sizeofTuple, + def.getFieldCount(), ptr, tptr, vcptr); + if (OK != rv) + { + deleteUserChunk(ptr); + if (vcptr) deleteUserChunk(vcptr); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Unable to update catalog table TABLE"); + return ErrSysInternal; + } + printDebug(DM_Database,"Inserted into TABLE:%s",name); + //add rows to FIELD + FieldIterator iter = def.getFieldIterator(); + CatalogTableFIELD cField(systemDatabase_); + rv = cField.insert(iter, tblID ,tptr); + if (OK != rv) + { + deleteUserChunk(ptr); + if (vcptr) deleteUserChunk(vcptr); + void *cptr, *ttptr;//Dummy as remove below needs both these OUT params + cTable.remove(name, cptr, ttptr); + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Unable to update catalog table FIELD"); + return ErrSysInternal; + } + printDebug(DM_Database,"Inserted into FIELD:%s",name); + systemDatabase_->releaseCheckpointMutex(); + printDebug(DM_Database,"Table Created:%s",name); + logFinest(Conf::logger, "Table Created %s" , name); + return OK; +} +DbRetVal DatabaseManagerImpl::renameTable(const char *oldName,const char *newName) +{ + void *chunk = NULL; + DbRetVal rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex for rename table"); + return ErrSysInternal; + } + CatalogTableTABLE cTable(systemDatabase_); + rv = cTable.renameTable(oldName,newName); + if (OK != rv) { + printError(ErrSysInternal, "Unable to rename table"); + systemDatabase_->releaseCheckpointMutex(); + return ErrSysInternal; + } + systemDatabase_->releaseCheckpointMutex(); + return OK; +} + +DbRetVal DatabaseManagerImpl::renameField(const char *tableName,const char *oldName,const char *newName) +{ + DbRetVal rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex for rename table"); + return ErrSysInternal; + } + CatalogTableFIELD fTable(systemDatabase_); + rv = fTable.renameField(tableName, oldName, newName); + if (OK != rv) { + printError(ErrSysInternal, "Unable to rename field."); + systemDatabase_->releaseCheckpointMutex(); + return ErrSysInternal; + } + systemDatabase_->releaseCheckpointMutex(); + return rv; +} + +//TODO::If any operation fails in between, then we may have some +//dangling tuples, say we have have rows in INDEX table +//which will not have any corresponding entries in TABLE +//CHANGE the sequence so that it deletes from the bottom as +//opposed to start from top as is written now +DbRetVal DatabaseManagerImpl::dropTable(const char *name) +{ + void *chunk = NULL; + void *tptr =NULL; + void *vcchunk = NULL; + DbRetVal rv = systemDatabase_->getXCheckpointMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex"); + return ErrSysInternal; + } + //remove the entry in TABLE + CatalogTableTABLE cTable(systemDatabase_); + rv = cTable.getChunkAndTblPtr(name, chunk, tptr, vcchunk); + if (OK != rv) { + systemDatabase_->releaseCheckpointMutex(); + printError(ErrSysInternal, "Table %s does not exist", name); + return ErrSysInternal; + } + CatalogTableFK cFK(systemDatabase_); + int noOfRelation =cFK.getNumFkTable(tptr); + if(noOfRelation) + { + printError(ErrSysInternal, "Unable to drop table due to relation exist.Drop child table..."); + systemDatabase_->releaseCheckpointMutex(); + return ErrSysInternal; + } + txnMgr()->rollback(lockMgr()); + txnMgr()->startTransaction(lockMgr(), READ_COMMITTED); + Transaction **trans = ProcessManager::getThreadTransAddr(systemDatabase_->procSlot); + rv = lMgr_->getExclusiveLock(chunk, trans); + if (rv !=OK) + { + systemDatabase_->releaseCheckpointMutex(); + txnMgr()->rollback(lockMgr()); + printError(ErrLockTimeOut, "Unable to acquire exclusive lock on the table\n"); + return rv; + } + rv = cTable.remove(name, chunk, tptr); + if (OK != rv) { + systemDatabase_->releaseCheckpointMutex(); + txnMgr()->rollback(lockMgr()); + printError(ErrSysInternal, "Unable to update catalog table TABLE"); + return ErrSysInternal; + } + printDebug(DM_Database,"Deleted from TABLE:%s",name); + + //remove the entries in the FIELD table + CatalogTableFIELD cField(systemDatabase_); + rv = cField.remove(tptr); + if (OK != rv) { + systemDatabase_->releaseCheckpointMutex(); + txnMgr()->rollback(lockMgr()); + printError(ErrSysInternal, "Unable to update catalog table FIELD"); + return ErrSysInternal; + } + printDebug(DM_Database,"Deleted from FIELD:%s",name); + + rv = deleteUserChunk((Chunk*)chunk); + if (OK != rv) { + systemDatabase_->releaseCheckpointMutex(); + txnMgr()->rollback(lockMgr()); + printError(rv, "Unable to delete the chunk"); + return rv; + } + printDebug(DM_Database,"Deleted UserChunk:%x", chunk); + + if (vcchunk != NULL) { + rv = deleteUserChunk((Chunk*)vcchunk); + if (OK != rv) { + systemDatabase_->releaseCheckpointMutex(); + txnMgr()->rollback(lockMgr()); + printError(rv, "Unable to delete the chunk"); + return rv; + } + printDebug(DM_Database,"Deleted UserChunk for Varchar:%x", chunk); + } + + //TODO::check whether indexes are available and drop that also. + CatalogTableINDEX cIndex(systemDatabase_); + int noIndexes = cIndex.getNumIndexes(tptr); + for (int i =1 ; i<= noIndexes; i++) { + char *idxName = cIndex.getIndexName(tptr, 1); + dropIndexInt(idxName, false); + } + bool isFkExist=cFK.isFkTable(tptr); + if(isFkExist) + { + dropForeignKey(tptr,false); + } + systemDatabase_->releaseCheckpointMutex(); + printDebug(DM_Database, "Deleted Table %s" , name); + logFinest(Conf::logger, "Deleted Table %s" , name); + rv = txnMgr()->commit(lockMgr()); + if (rv !=OK) + { + printError(ErrLockTimeOut, "Unable to release exclusive lock on the table\n"); + return rv; + } + return OK; +} + +//Return values: NULL for table not found +Table* DatabaseManagerImpl::openTable(const char *name,bool checkpkfk) +{ + DbRetVal ret = OK; + //TODO::store table handles in list so that if it is + //not closed by the application. destructor shall close it. + TableImpl *table = new TableImpl(); + table->setDB(db_); + table->setSystemDB(systemDatabase_); + table->setLockManager(lMgr_); + table->setTrans(ProcessManager::getThreadTransAddr(systemDatabase_->procSlot)); + + //to store the chunk pointer of table + void *chunk = NULL; + void *vcchunk = NULL; + + //to store the tuple pointer of the table + void *tptr =NULL; + + //TODO::need to take shared lock on the table so that + //all ddl operation will be denied on that table + //which includes index creation, alter table + + DbRetVal rv = systemDatabase_->getAllocDatabaseMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get database mutex"); + delete table; + return NULL; + } + CatalogTableTABLE cTable(systemDatabase_); + ret = cTable.getChunkAndTblPtr(name, chunk, tptr, vcchunk); + if ( OK != ret) + { + systemDatabase_->releaseAllocDatabaseMutex(); + delete table; + printError(ErrNotExists, "Table not exists %s", name); + return NULL; + } + CTABLE *tTuple = (CTABLE*)tptr; + table->setTableInfo(tTuple->tblName_, tTuple->tblID_, tTuple->length_, + tTuple->numFlds_, tTuple->numIndexes_, + tTuple->chunkPtr_, tTuple->varcharChunkPtr_); + rv = table->lock(true); //take shared lock + if (rv !=OK) + { + printError(ErrLockTimeOut, "Unable to acquire shared lock on the table\n"); + systemDatabase_->releaseAllocDatabaseMutex(); + delete table; + return NULL; + } + + if (tTuple->numFlds_ <= 32) + { + table->isIntUsedForNULL = true; + table->iNullInfo = 0; + table->iNotNullInfo =0; + } + else + { + table->isIntUsedForNULL = false; + int noFields = os::align(tTuple->numFlds_); + table->cNullInfo = (char*) malloc(noFields); + table->cNotNullInfo = (char*) malloc(noFields); + for (int i =0 ; i < noFields; i++) table->cNullInfo[i] =0; + for (int i =0 ; i < noFields; i++) table->cNotNullInfo[i] =0; + + } + + //get field information from FIELD table + CatalogTableFIELD cField(systemDatabase_); + table->ptrToAuto = cField.getFieldInfo(tptr, table->fldList_); + + //populate the notnull info + FieldIterator fIter = table->fldList_.getIterator(); + int fldpos=1; + while (fIter.hasElement()) + { + FieldDef *def = fIter.nextElement(); + if (table->isIntUsedForNULL) { + if (def->isNull_) SETBIT(table->iNotNullInfo, fldpos-1); + } + else { + if (def->isNull_) table->cNotNullInfo[fldpos-1] = 1; + } + fldpos++; + } + + //get the number of indexes on this table + //and populate the indexPtr array + CatalogTableINDEX cIndex(systemDatabase_); + table->numIndexes_ = cIndex.getNumIndexes(tptr); + if (table->numIndexes_) { + table->indexPtr_ = new char*[table->numIndexes_]; + table->idxInfo = new IndexInfo*[table->numIndexes_]; + } + else + { + table->indexPtr_ = NULL; + } + cIndex.getIndexPtrs(tptr, table->indexPtr_); + for (int i =0 ; i < table->numIndexes_; i++ ) + { + HashIndexInfo *hIdxInfo = new HashIndexInfo(); + CatalogTableINDEXFIELD cIndexField(systemDatabase_); + cIndexField.getFieldInfo(table->indexPtr_[i], hIdxInfo->idxFldList); + ChunkIterator citer = CatalogTableINDEX::getIterator(table->indexPtr_[i]); + hIdxInfo->indexPtr = table->indexPtr_[i]; + hIdxInfo->indType = ((CINDEX*)hIdxInfo->indexPtr)->indexType_; + hIdxInfo->noOfBuckets = CatalogTableINDEX::getNoOfBuckets(table->indexPtr_[i]); + FieldIterator fIter = hIdxInfo->idxFldList.getIterator(); + bool firstFld = true; + while (fIter.hasElement()) + { + FieldDef *def = fIter.nextElement(); + if (firstFld) + { + hIdxInfo->fldOffset = table->fldList_.getFieldOffset(def->fldName_); + hIdxInfo->type = table->fldList_.getFieldType(def->fldName_); + hIdxInfo->compLength = table->fldList_.getFieldLength(def->fldName_); + firstFld = false; + }else { + hIdxInfo->type = typeComposite; + hIdxInfo->compLength = hIdxInfo->compLength + + table->fldList_.getFieldLength(def->fldName_); + } + } + + hIdxInfo->isUnique = CatalogTableINDEX::getUnique(table->indexPtr_[i]); + hIdxInfo->buckets = (Bucket*)citer.nextElement(); + table->idxInfo[i] = (IndexInfo*) hIdxInfo; + } + systemDatabase_->releaseAllocDatabaseMutex(); + //Foreign key Operation + if(checkpkfk){ + CatalogTableFK cFk(systemDatabase_); + int totalFld=0; + table->numFkRelation_ = cFk.getNumFkTable(tptr); + if (table->numFkRelation_) { + table->isPkTbl=true;//TODO:for Delete In casecade + totalFld=cFk.getNoOfFkTable(tptr); + //printDebug(DM_TEST,"Total table is %d\n",totalFld); + char **fptr = new char* [totalFld]; + cFk.getFkTableName(tptr,fptr); + for(int count=0; count < totalFld; count++){ + //printDebug(DM_TEST,"FK Name is %s\n",fptr[count]); + Table *pkTable=openTable(fptr[count],false); + if (pkTable) table->tblFkList.append(pkTable); + else { + printError(ErrSysInternal, "Unable to open foreign key tables"); + delete[] fptr; + pkTable->close(); + return NULL; + } + } + delete[] fptr; + + } + char *tblName = NULL; + table->isFkTbl = cFk.isFkTable(tptr); + if(table->isFkTbl) + { + totalFld=cFk.getNoOfPkTable(tptr); + char **fptr = new char* [totalFld]; + cFk.getPkTableName(tptr,fptr); + for(int count=0; counttblList.append(fkTable); + else { + printError(ErrSysInternal, "Unable to open foreign key tables"); + delete[] fptr; + fkTable->close(); + return NULL; + } + } + delete[] fptr; + } + } + printDebug(DM_Database,"Opening table handle name:%s chunk:%x numIndex:%d", + name, chunk, table->numIndexes_); + logFinest(Conf::logger, "Opening Table %s" , name); + return table; +} + +List DatabaseManagerImpl::getAllTableNames(int *retval) +{ + DbRetVal ret = OK; + //to store the tuple pointer of the table + void *tptr =NULL; + + /*DbRetVal rv = systemDatabase_->getSCheckpointMutex(); + if (OK != rv) { + printError(ErrSysInternal, "Unable to get checkpoint mutex"); + if(retval) *retval = rv; + List tableList; + return tableList; + }*/ + CatalogTableTABLE cTable(systemDatabase_); + List tableList = cTable.getTableList(); + //systemDatabase_->releaseCheckpointMutex(); + return tableList; +} + + +//Return values: -1 for table not found +void DatabaseManagerImpl::closeTable(Table *table) +{ + printDebug(DM_Database,"Closing table handle: %x", table); + if (NULL == table) return; + table->unlock(); + /* TableImpl *fkTbl =NULL; + ListIterator tblIter = ((TableImpl*)table)->tblList.getIterator(); + tblIter.reset(); + while (tblIter.hasElement()){ + fkTbl = (TableImpl *) tblIter.nextElement(); + closeTable(fkTbl); + } + ((TableImpl*)table)->tblList.reset(); + tblIter = ((TableImpl*)table)->tblFkList.getIterator(); + tblIter.reset(); + while (tblIter.hasElement()){ + fkTbl = (TableImpl *) tblIter.nextElement(); + closeTable(fkTbl); + } + ((TableImpl*)table)->tblFkList.reset();*/ + if (table) delete table; table = NULL; + logFinest(Conf::logger, "Closing Table"); +} + +int DatabaseManagerImpl::getNoOfPagesForTable(char *tblName) +{ + Table *tbl = openTable(tblName); + if (NULL == tbl) { + printError(ErrSysInternal, "Unable to open table %s", tblName); + return 0; + } + TableImpl *tb = (TableImpl *) tbl; + int pages = 0; + if (tb->numTuples()) pages = tb->pagesUsed(); + closeTable(tbl); + return pages; +} + diff --git a/src/storage/Makefile.am b/src/storage/Makefile.am index 9ecc362e..60cc48e4 100644 --- a/src/storage/Makefile.am +++ b/src/storage/Makefile.am @@ -7,7 +7,8 @@ libcsql_la_SOURCES = BucketIter.cxx TreeIter.cxx BucketList.cxx \ TableConfig.cxx \ CatalogTables.cxx CatalogTablesIdx.cxx CatalogTablesFk.cxx \ ChunkIterator.cxx Condition.cxx Connection.cxx Database.cxx \ - DatabaseManagerImpl.cxx DatabaseRecovery.cxx \ + DatabaseManagerImpl.cxx DbMgrTableImpl.cxx DbMgrIndexImpl.cxx \ + DbMgrFkImpl.cxx DatabaseRecovery.cxx \ FieldList.cxx Index.cxx LockManager.cxx \ LockTable.cxx \ PageInfo.cxx PredicateImpl.cxx SessionImpl.cxx \ -- 2.11.4.GIT