From bfc3daa16fa94c0ea51f572b969632dfec9fe03e Mon Sep 17 00:00:00 2001 From: prabatuty Date: Sun, 3 Jul 2011 04:22:12 +0000 Subject: [PATCH] reorg files --- src/storage/AggTableImpl.cxx | 676 ----------------------------- src/storage/HashIndex.cxx | 685 ----------------------------- src/storage/Index.cxx | 50 --- src/storage/JoinTableImpl.cxx | 689 ----------------------------- src/storage/OrderByTree.cxx | 133 ------ src/storage/OrderTableImpl.cxx | 468 -------------------- src/storage/TableDef.cxx | 142 ------ src/storage/TableImpl.cxx | 748 -------------------------------- src/storage/TableImplModifyOp.cxx | 885 -------------------------------------- src/storage/TableImplReadOp.cxx | 578 ------------------------- src/storage/TreeIndex.cxx | 496 --------------------- src/storage/TreeIter.cxx | 333 -------------- src/storage/TreeNode.cxx | 813 ---------------------------------- src/storage/TrieIndex.cxx | 399 ----------------- 14 files changed, 7095 deletions(-) delete mode 100644 src/storage/AggTableImpl.cxx delete mode 100644 src/storage/HashIndex.cxx delete mode 100644 src/storage/Index.cxx delete mode 100644 src/storage/JoinTableImpl.cxx delete mode 100644 src/storage/OrderByTree.cxx delete mode 100644 src/storage/OrderTableImpl.cxx delete mode 100644 src/storage/TableDef.cxx delete mode 100644 src/storage/TableImpl.cxx delete mode 100644 src/storage/TableImplModifyOp.cxx delete mode 100644 src/storage/TableImplReadOp.cxx delete mode 100644 src/storage/TreeIndex.cxx delete mode 100644 src/storage/TreeIter.cxx delete mode 100644 src/storage/TreeNode.cxx delete mode 100644 src/storage/TrieIndex.cxx diff --git a/src/storage/AggTableImpl.cxx b/src/storage/AggTableImpl.cxx deleted file mode 100644 index ac00be62..00000000 --- a/src/storage/AggTableImpl.cxx +++ /dev/null @@ -1,676 +0,0 @@ -/*************************************************************************** - * 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 -static char AggNames[][20] = -{ - "MIN", "MAX", "SUM", "AVG", "COUNT", "" -}; - -AggTableImpl::AggTableImpl() -{ - tableHdl = NULL; - curTuple = NULL; - havingPred = NULL; - groupSize = 0; - aggNodeSize = 0; - prjNullInfo = 0; - grpNullInfo = 0; - grpFldBuffer = NULL; - optGrpIntNoNull = false; - grpBindBuf = NULL; -} - -AggTableImpl::~AggTableImpl() -{ - //free memory allocated. make sure that field buffers are freed only once. - //for stmts which has more than one agg on same field needs to be handled safely - closeScan(); - ListIterator iter = fldList.getIterator(); - AggFldDef *elem; - while (iter.hasElement()) - { - elem = (AggFldDef*) iter.nextElement(); - if(!elem->alreadyBinded) free(elem->bindBuf); - delete elem; - } - fldList.reset(); - - ListIterator giter = fldGroupList.getIterator(); - while (giter.hasElement()) - { - elem = (AggFldDef*) giter.nextElement(); - if(!elem->alreadyBinded) free(elem->bindBuf); - delete elem; - } - fldGroupList.reset(); - if (tableHdl != NULL) tableHdl->close(); - tableHdl = NULL; - ::free(grpFldBuffer); -} - -void *AggTableImpl::getBindFldAddr(const char *name) -{ - printError(ErrBadCall, "AggTableImpl getBindFldAdddr not implemented\n"); - return NULL; -} - -DbRetVal AggTableImpl::bindFld(const char *name, void *val, bool dummy) -{ - printError(ErrBadCall, "AggTableImpl bindFld not implemented\n"); - return ErrBadCall; -} - -DbRetVal AggTableImpl::bindFld(const char *fldname, AggType aggType, void *val) -{ - FieldInfo *info = new FieldInfo(); - DbRetVal rv = tableHdl->getFieldInfo(fldname, info); - if (OK != rv) { delete info; return rv; } - AggFldDef *def = new AggFldDef(); - strcpy(def->fldName, fldname); - def->type = info->type; - def->length= info->length; - def->appBuf = val; - def->aType=aggType; - def->bindBuf = NULL; - def->alreadyBinded = false; - - //if underlying tablehandle is TableImpl, then set isNullable - def->isNullable = true; - if (info->isNull || info->isPrimary || - info->isDefault || info->isAutoIncrement) { - def->isNullable = false; - } - if (NULL == tableHdl->getName()) def->isNullable=true; - - ListIterator iter = fldList.getIterator(); - AggFldDef *elem; - //If it is already binded, then use the same buffer which is binded. - //this code is to handle statements which have more aggregates on same field - while (iter.hasElement()) - { - elem = (AggFldDef*) iter.nextElement(); - if (strcmp(elem->fldName, fldname)==0) - { - def->bindBuf = elem->bindBuf; - def->alreadyBinded = true; - break; - } - } - if (!def->bindBuf) - { - def->bindBuf = AllDataType::alloc(def->type, def->length); - rv = tableHdl->bindFld(fldname, def->bindBuf); - if (OK !=rv) { - delete info; - ::free(def->bindBuf); - delete def; - return rv; - } - } - fldList.append(def); - delete info; - return OK; -} - -DbRetVal AggTableImpl::setGroup(const char *fldname, void *val) -{ - FieldInfo *info = new FieldInfo(); - DbRetVal rv = tableHdl->getFieldInfo(fldname, info); - if (rv !=OK) { delete info; return rv; } - AggFldDef *groupFld=new AggFldDef(); - strcpy(groupFld->fldName, fldname); - groupFld->type = info->type; - groupFld->length = info->length; - groupFld->appBuf = val; - groupFld->bindBuf = NULL; - - groupFld->isNullable = true; - if (info->isNull || info->isPrimary || - info->isDefault || info->isAutoIncrement) { - groupFld->isNullable = false; - } - if (NULL == tableHdl->getName()) groupFld->isNullable=true; - - ListIterator iter = fldList.getIterator(); - AggFldDef *elem; - - while (iter.hasElement()) - { - elem = (AggFldDef*) iter.nextElement(); - if (strcmp(elem->fldName, fldname)==0) - { - groupFld->bindBuf = elem->bindBuf; - groupFld->alreadyBinded = true; - break; - } - } - if (!groupFld->bindBuf) - { - groupFld->bindBuf = AllDataType::alloc(groupFld->type, groupFld->length); - rv = tableHdl->bindFld(fldname, groupFld->bindBuf); - if (rv !=OK) { - delete info; - ::free(groupFld->bindBuf); - delete groupFld; - return rv; - } - } - - fldGroupList.append(groupFld); - delete info; - return OK; -} - -bool AggTableImpl::isFldPresentInGrp(char *fname) -{ - ListIterator iter = fldGroupList.getIterator(); - AggFldDef *grpFld=NULL; - while (iter.hasElement()) - { - grpFld=(AggFldDef *)iter.nextElement(); - if(0==strcmp(fname,grpFld->fldName)) return true; - } - return false; -} - -int AggTableImpl::getAggOffset(char *fname, AggType aggType) -{ - ListIterator iter = fldList.getIterator(); - AggFldDef *projDef=NULL; - int offset = groupSize + sizeof(prjNullInfo); - while (iter.hasElement()) - { - projDef=(AggFldDef *)iter.nextElement(); - if(0==strcmp(fname, projDef->fldName) && aggType == projDef->aType) - { - return offset; - } - else { - if (projDef->aType == AGG_AVG) - offset = offset + sizeof (double)+ sizeof(int); - else if (projDef->aType == AGG_COUNT) - offset = offset + sizeof(int); - else - offset = offset + os::align(projDef->length); - } - } - printError(ErrSysFatal, "Aggregate condition not found in projection list %s", fname); - return offset; -} - -int AggTableImpl::computeGrpNodeSize() -{ - ListIterator iter = fldGroupList.getIterator(); - AggFldDef *grpFld=NULL; - int totalGrpNodeSize=sizeof(int); - while (iter.hasElement()) - { - grpFld=(AggFldDef *)iter.nextElement(); - totalGrpNodeSize=totalGrpNodeSize + os::align(grpFld->length); - } - return totalGrpNodeSize; -} - -DbRetVal AggTableImpl::copyValuesFromGrpBindBuf(char *buffer, char *fname) -{ - ListIterator iter = fldGroupList.getIterator(); - AggFldDef *grpFld=NULL; - while ((grpFld = (AggFldDef*)iter.nextElement()) != NULL) - { - //grpFld=(AggFldDef *)iter.nextElement(); - if(0==strcmp(fname,grpFld->fldName)) - { - AllDataType::copyVal(buffer, grpFld->bindBuf, grpFld->type, - grpFld->length); - break; - } - } - return OK; -} - -DbRetVal AggTableImpl::optimize() -{ - AggFldDef *grpFld=NULL; - optGrpIntNoNull= false; - if (groupSize == sizeof(int)+ sizeof(int)) - { - ListIterator iter = fldGroupList.getIterator(); - grpFld = (AggFldDef*)iter.nextElement(); - if (!grpFld->isNullable && grpFld->type == typeInt) - { - optGrpIntNoNull=true; - grpBindBuf = grpFld->bindBuf; - aggNodeMap.setGrpIntNoNull(); - } - } - return OK; -} - -DbRetVal AggTableImpl::execute() -{ - ListIterator iter = fldList.getIterator(); - AggFldDef *def; - aggNodeSize = groupSize = computeGrpNodeSize(); - aggNodeMap.setKeySize(groupSize); - optimize(); - - grpFldBuffer = (char*) ::malloc(groupSize); - aggNodeSize += sizeof(long long); // for proj field null Info - while (iter.hasElement()) - { - def = (AggFldDef*) iter.nextElement(); - if (def->aType == AGG_AVG) { - aggNodeSize += sizeof(double); - aggNodeSize += sizeof(int);//for count - } - else if (def->aType == AGG_COUNT) aggNodeSize += sizeof(int); - else aggNodeSize += os::align(def->length); - } - void *tuple = NULL; - int offset=0; - tableHdl->execute(); - aggNodes.reset(); - int groupOffset = groupSize; - while((tuple = tableHdl->fetch()) != NULL) - { - char *buffer = (char*)insertOrGetAggNode(); - iter.reset(); - offset = groupOffset; - char *nullInfo = buffer + offset; - prjNullInfo = *(long long *) nullInfo; - offset += sizeof(long long); - int colpos = 1; - while ((def = (AggFldDef*)iter.nextElement()) != NULL) - { - //def = (AggFldDef*) iter.nextElement(); - if (def->isNullable && tableHdl->isFldNull(def->fldName)) { - if (def->aType == AGG_AVG) - offset = offset + sizeof(double) + sizeof(int); - else if (def->aType == AGG_COUNT) offset += sizeof(int); - else offset = offset + os::align(def->length); - colpos++; - continue; - } - bool result=false; bool isNull=false; - isNull = isFldNull(colpos); - switch(def->aType) - { - case AGG_MIN: { - if (!isNull) { - result = AllDataType::compareVal(buffer+offset, - def->bindBuf, OpGreaterThanEquals, def->type, - def->length); - } - if (result || isNull) - AllDataType::copyVal(buffer+offset, def->bindBuf, - def->type, def->length); - break; - } - case AGG_MAX: { - if (!isNull) { - result = AllDataType::compareVal(buffer+offset, - def->bindBuf, OpLessThanEquals, def->type, - def->length); - } - if (result || isNull) - AllDataType::copyVal(buffer+offset, def->bindBuf, - def->type, def->length); - break; - } - case AGG_SUM: { - AllDataType::addVal(buffer+offset, def->bindBuf, def->type); - break; - } - case AGG_AVG: { - double tmpBuf=0.0; - AllDataType::convertToDouble(&tmpBuf, def->bindBuf, - def->type); - AllDataType::addVal(buffer+offset, &tmpBuf, typeDouble); - (*(int*)(buffer+offset + sizeof(double)))++; - break; - } - case AGG_COUNT: - (*(int*)(buffer+offset))++; - break; - case AGG_UNKNOWN: - { - copyValuesFromGrpBindBuf(buffer+offset, def->fldName); - break; - } - } - clearFldNull(colpos); - if (def->aType == AGG_AVG) - offset = offset + sizeof(double) + sizeof(int); - else if (def->aType == AGG_COUNT) - offset += sizeof(int); - else - offset = offset + os::align(def->length); - colpos++; - } - memcpy(nullInfo, &prjNullInfo, sizeof(long long)); - } - aggNodeIter = aggNodes.getIterator(); - iter.reset(); - char *element; - offset = groupOffset+sizeof(long long); - while (iter.hasElement()) { - def = (AggFldDef*) iter.nextElement(); - if(def->aType == AGG_AVG) { - aggNodeIter.reset(); - while (aggNodeIter.hasElement()) { - element = (char*)aggNodeIter.nextElement(); - AllDataType::divVal((double *) (element+offset), - *(int *)(element+offset+ sizeof(double)), typeDouble); - } - offset = offset + sizeof(double) + sizeof(int); - continue; - } - else if (def->aType == AGG_COUNT) - offset += sizeof(int); - else - offset = offset + os::align(def->length); - } - aggNodeIter.reset(); - tableHdl->closeScan(); - return OK; -} - -void* AggTableImpl::getGroupValueBuffer() -{ - memset(grpFldBuffer, 0, groupSize); - AggFldDef *def; - char *offset= (char*)grpFldBuffer; - if (optGrpIntNoNull) { - *(int*)offset = *(int*)grpBindBuf; - return grpFldBuffer; - } - grpNullInfo = 0; - ListIterator giter = fldGroupList.getIterator(); - int colpos = 1; - while((def = (AggFldDef*) giter.nextElement()) != NULL) - { - if (def->isNullable && tableHdl->isFldNull(def->fldName)) markFldNull(colpos); - else AllDataType::copyVal(offset, def->bindBuf, def->type, def->length); - offset = offset + os::align(def->length); - colpos++; - } - memcpy(offset, &grpNullInfo, sizeof(int)); - return grpFldBuffer; -} - -void* AggTableImpl::insertOrGetAggNode() -{ - char *element; - if (0 == fldGroupList.size()) { - ListIterator aiter = aggNodes.getIterator(); - if (aiter.hasElement()) return aiter.nextElement(); - } else { - void *grpBuffer = getGroupValueBuffer(); - element = (char*) aggNodeMap.find(grpBuffer); - if (element) return element; - } - - element = (char*)malloc(aggNodeSize); - memset(element, 0, aggNodeSize); - ListIterator iter = fldList.getIterator(); - AggFldDef *def; - char *offset = element; - grpNullInfo = 0; - //offset += sizeof(int); - ListIterator giter = fldGroupList.getIterator(); - int colpos = 1; - while(giter.hasElement()) - { - def = (AggFldDef*) giter.nextElement(); - if(def->isNullable && tableHdl->isFldNull(def->fldName)) - markFldNull(colpos); - else - AllDataType::copyVal(offset, def->bindBuf, def->type,def->length); - offset = offset + os::align(def->length); - colpos++; - } - memcpy(offset, &grpNullInfo, sizeof(int)); - offset += sizeof(int); - memset(offset, 0xff, sizeof(long long)); - offset += sizeof(long long); - while (iter.hasElement()) - { - def = (AggFldDef*) iter.nextElement(); - switch(def->aType) { - case AGG_MIN: - case AGG_MAX: - { - AllDataType::copyVal(offset, def->bindBuf, def->type, - def->length); - break; - } - case AGG_SUM: - { - AllDataType::copyZeroVal(offset, def->type, def->length); - break; - } - case AGG_AVG: { - *(double*)(offset)=0; - *(int*)(offset+ sizeof(double))=0; //count - break; - } - case AGG_COUNT: { *(int*)(offset)=0; break; } - } - if (def->aType == AGG_AVG) - offset = offset + sizeof(double) + sizeof(int); - else if (def->aType == AGG_COUNT) - offset += sizeof(int); - else - offset = offset + os::align(def->length); - } - aggNodes.append(element); - aggNodeMap.insert(element); - return element; -} - -void* AggTableImpl::fetch() -{ - while(aggNodeIter.hasElement()) - { - void *elem = aggNodeIter.nextElement(); - bool result=false; - if (havingPred) { - PredicateImpl *pImpl = (PredicateImpl*)havingPred; - pImpl->evaluateForHaving(result , this, elem); - if (!result) continue; - } - copyValuesToBindBuffer(elem); - return elem; - } - return NULL; - -} - -void* AggTableImpl::fetch(DbRetVal &rv) -{ - rv = OK; - return fetch(); -} - -void* AggTableImpl::fetchNoBind() -{ - if(aggNodeIter.hasElement()) - { - void *elem = aggNodeIter.nextElement(); - return elem; - } - else - return NULL; -} - -void* AggTableImpl::fetchNoBind(DbRetVal &rv) -{ - rv = OK; - return fetchNoBind(); -} - -DbRetVal AggTableImpl::copyValuesToBindBuffer(void *elem) -{ - char *element = (char*)elem; - //Iterate through the bind list and copy the value here - ListIterator fIter = fldList.getIterator(); - AggFldDef *def; - char *colPtr=element+groupSize; - prjNullInfo = *(long long *) colPtr; - colPtr += sizeof(long long); - int colpos = 1; - while (fIter.hasElement()) - { - def = (AggFldDef*) fIter.nextElement(); - if (isFldNull(colpos)) { - if (def->aType == AGG_AVG) - colPtr += sizeof(double) + sizeof(int); - else if (def->aType == AGG_COUNT) - colPtr += sizeof(int); - else - colPtr += os::align(def->length); - colpos++; - continue; - } - if (NULL != def->appBuf) { - if (def->aType == AGG_AVG) { - os::memcpy(def->appBuf, colPtr, sizeof(double)); - colPtr = colPtr + sizeof(double) + sizeof(int); - } - else if (def->aType == AGG_COUNT) { - AllDataType::copyVal(def->appBuf, colPtr, typeInt, sizeof(int)); - colPtr += sizeof(int); - } - else { - AllDataType::copyVal(def->appBuf, colPtr, def->type, - def->length); - colPtr = colPtr + os::align(def->length); - } - } - colpos++; - } - return OK; -} - -long AggTableImpl::numTuples() -{ - return aggNodes.size(); -} - -DbRetVal AggTableImpl::closeScan() -{ - aggNodeIter.reset(); - ListIterator aiter = aggNodes.getIterator(); - char *element; - while (aiter.hasElement()) { - element = (char*)aiter.nextElement(); - free(element); - } - aggNodes.reset(); - aggNodeMap.removeAll(); - if (tableHdl) tableHdl->closeScan(); - return OK; -} - -DbRetVal AggTableImpl::close() -{ - havingPred = NULL; - delete this; - return OK; -} - -bool AggTableImpl::isFldNull(const char *name) -{ - ListIterator it = fldList.getIterator(); - int colpos = 1; - char fldName[IDENTIFIER_LENGTH]; - AggType atp = getAggType(name, fldName); - while (it.hasElement()) { - AggFldDef *def = (AggFldDef *) it.nextElement(); - if (!def->isNullable) return false; - if (atp != AGG_UNKNOWN) { - if (strcmp(def->fldName, fldName)==0 && def->aType == atp) break; - } - else if (strcmp(def->fldName, name)==0) break; - colpos++; - } - return isFldNull(colpos); -} - -void AggTableImpl::printPlan(int space) -{ - char spaceBuf[IDENTIFIER_LENGTH]; - memset(spaceBuf, 32, IDENTIFIER_LENGTH); - spaceBuf[space] = '\0'; - PredicateImpl* predImpl = (PredicateImpl*) havingPred; - printf("%s \n", spaceBuf); - printf("%s \n", spaceBuf); - AggFldDef *fldDef=NULL; - ListIterator iter = fldList.getIterator(); - while ((fldDef = (AggFldDef*)iter.nextElement()) != NULL) - { - if (fldDef->aType == AGG_UNKNOWN) - printf("%s %s \n", spaceBuf, - fldDef->fldName); - else - printf("%s %s(%s) \n", spaceBuf, - AggNames[fldDef->aType -1], fldDef->fldName); - } - printf("%s \n", spaceBuf); - printf("%s \n", spaceBuf); - ListIterator giter = fldGroupList.getIterator(); - while ((fldDef = (AggFldDef*)giter.nextElement()) != NULL) - { - printf("%s %s \n", spaceBuf, fldDef->fldName); - } - printf("%s \n", spaceBuf); - if (havingPred) predImpl->print(space); - printf("%s \n", spaceBuf); - if (tableHdl) tableHdl->printPlan(space+2); - return; -} - -AggType AggTableImpl::getAggType(const char *name, char *fldName) -{ - char *ptr = (char *)name; - AggType atp = AGG_UNKNOWN; - if (strncmp(name, "COUNT", 5) == 0) { - ptr += strlen("COUNT("); - atp = AGG_COUNT; - } else if (strncmp(name, "MIN", 3) == 0) { - ptr += strlen("MIN("); - atp = AGG_MIN; - } else if (strncmp(name, "MAX", 3) == 0) { - ptr += strlen("MAX("); - atp = AGG_MAX; - } else if (strncmp(name, "SUM", 3) == 0) { - ptr += strlen("SUM("); - atp = AGG_SUM; - } else if (strncmp(name, "AVG", 3) == 0) { - ptr += strlen("AVG("); - atp = AGG_AVG; - } - if (atp == AGG_UNKNOWN) return atp; - strcpy(fldName, ptr); - ptr = fldName; - while (*ptr != ')') ptr++; - *ptr = '\0'; - return atp; -} diff --git a/src/storage/HashIndex.cxx b/src/storage/HashIndex.cxx deleted file mode 100644 index cc1f8168..00000000 --- a/src/storage/HashIndex.cxx +++ /dev/null @@ -1,685 +0,0 @@ -/*************************************************************************** - * 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 - -/* Defines `hashpjw' function by P.J. Weinberger - [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, - */ - -unsigned int hashString(char *strVal) -{ - unsigned int hval, g; - hval = 0; - char *str =strVal; - while (*str != '\0') - { - hval <<= 4; - hval += (unsigned int) *str++; - g = hval & ((unsigned int) 0xf << (32 - 4)); - if (g != 0) - { - hval ^= g >> (32 - 8); - hval ^= g; - } - } - return hval; -} - -unsigned int hashBinary(char *strVal, int length) -{ - unsigned int hval, g; - hval = 0; - char *str =strVal; - int iter = 0; - while (iter != length) - { - hval <<= 4; - hval += (unsigned int) *str++; - g = hval & ((unsigned int) 0xf << (32 - 4)); - if (g != 0) - { - hval ^= g >> (32 - 8); - hval ^= g; - } - iter++; - } - return hval; -} - -unsigned int HashIndex::computeHashBucket(DataType type, void *key, int noOfBuckets, int length) - -{ - if (typeInt == type) { - int val = *(int*)key; - return val % noOfBuckets; - }else if (typeString == type || typeVarchar == type) { - unsigned int val = hashString((char*)key); - return val % noOfBuckets; - }else if (typeShort == type) { - short val = *(short*) key; - return val % noOfBuckets; - }else if (typeLong == type) { - long val = *(long*) key; - return val % noOfBuckets; - }else if (typeLongLong == type) { - long long val = *(long long*) key; - return val % noOfBuckets; - }else if (typeByteInt == type) { - ByteInt val = *(ByteInt*)key; - return val % noOfBuckets; - }else if (typeDate == type) { - int val = *(int*)key; - return val % noOfBuckets; - }else if (typeTime == type) { - int val = *(int*)key; - return val % noOfBuckets; - }else if (typeComposite == type) { - unsigned int val = hashBinary((char*)key, length); - return val % noOfBuckets; - }else if (typeBinary == type) { - unsigned int val = hashBinary((char*)key, length); - return val % noOfBuckets; - }else if (typeULong == type) { - unsigned long val = *(unsigned long*)key; - return val % noOfBuckets; - } - printError(ErrSysFatal,"Type not supported for hashing\n"); - return -1; -} - -bool HashIndex::checkForUniqueKey(IndexNode *head, HashIndexInfo *info, void *tuple) -{ - if (!head) return false; - int offset = info->fldOffset; - DataType type = info->type; - BucketList list(head); - BucketIter iter = list.getIterator(); - IndexNode *node; - void *bucketTuple; - printDebug(DM_HashIndex, "HashIndex insert Checking for unique"); - bool res = false; - - while((node = iter.next()) != NULL) - { - bucketTuple = node->ptrToTuple_; - if (type == typeComposite) { - FieldIterator fldIter = info->idxFldList.getIterator(); - int i = 0; - while (fldIter.hasElement()) { - FieldDef *def = fldIter.nextElement(); - if (def->type_ != typeVarchar) { - res = AllDataType::compareVal( - (char *)bucketTuple + def->offset_, - (char *)tuple + def->offset_, - OpEquals, def->type_, def->length_); - } else { - char *tvcptr = (char *) *(long *) - ((char *)tuple + def->offset_); - char *btvcptr = (char *) *(long *) - ((char *)bucketTuple + def->offset_); - res = AllDataType::compareVal(tvcptr, btvcptr, - OpEquals, def->type_, def->length_); - } - if (!res) break; - } - } - else { - if (type != typeVarchar) - res = AllDataType::compareVal((void*)((char*)bucketTuple +offset), - (void*)((char*)tuple +offset), OpEquals, - type, info->compLength); - else - res = AllDataType::compareVal((void*)*(long *)((char*)bucketTuple +offset), - (void*)*(long *)((char*)tuple +offset), - OpEquals,type, info->compLength); - } - if (res) - { - if (type == typeLongLong) - printError(ErrUnique, "Unique key violation for id:%lld", - *(long long*) ((char*)tuple +offset) ); - else - printError(ErrUnique, "Unique key violation"); - return true; - } - } - return false; -} - -DbRetVal HashIndex::insert(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool loadFlag) -{ - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - DbRetVal rc = OK; - int noOfBuckets = info->noOfBuckets; - int offset = info->fldOffset; - DataType type = info->type; - - printDebug(DM_HashIndex, "Inserting hash index node for %s", iptr->indName_); - ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); - Bucket* buckets = (Bucket*)citer.nextElement(); - void *keyPtr =(void*)((char*)tuple + offset); - int bucketNo = 0; - if (type == typeComposite) { - char *keyBuffer = (char*) malloc(info->compLength); - memset(keyBuffer, 0, info->compLength); - void* keyStartBuffer = keyBuffer; - FieldIterator iter = info->idxFldList.getIterator(); - while(iter.hasElement()) - { - FieldDef *def = iter.nextElement(); - keyPtr = (char *)tuple + def->offset_; - if (def->type_ != typeVarchar) { - AllDataType::copyVal(keyBuffer, keyPtr, def->type_, - def->length_); - } else { - void *ptr = (void *) *(long *) keyPtr; - if (ptr) - AllDataType::copyVal(keyBuffer, ptr, def->type_, - def->length_); - } - keyBuffer = keyBuffer + AllDataType::size(def->type_,def->length_); - } - bucketNo = computeHashBucket(type, keyStartBuffer, noOfBuckets, - info->compLength); - ::free(keyStartBuffer); - } - else { - if (type != typeVarchar) - bucketNo = - computeHashBucket(type, keyPtr, noOfBuckets, info->compLength); - else { - void *ptr = (void *) *(long *) keyPtr; - if (ptr) - bucketNo = computeHashBucket(type, ptr, noOfBuckets, - info->compLength); - else bucketNo = 0; - } - } - printDebug(DM_HashIndex, "HashIndex insert bucketno %d", bucketNo); - Bucket *bucket = &(buckets[bucketNo]); - HashUndoLogInfo hInfo; - hInfo.metaData_ = tbl->db_->getMetaDataPtr(); - hInfo.bucket_ = bucket; - hInfo.tuple_ = tuple; - hInfo.hChunk_ = ((CINDEX *)indexPtr)->hashNodeChunk_; - hInfo.keyPtr_ = keyPtr; - - IndexNode *head = (IndexNode*) bucket->bucketList_; - if (info->isUnique) - { - bool isKeyPresent = checkForUniqueKey(head, info, tuple); - if (isKeyPresent) return ErrUnique; - } - Chunk *hIdxNodeChunk = (Chunk*)iptr->hashNodeChunk_; - printDebug(DM_HashIndex, "HashIndex insert into bucket list"); - if (!head) - { - printDebug(DM_HashIndex, "HashIndex insert head is empty"); - DbRetVal rv = OK; - IndexNode *firstNode= NULL; - - int tries=0; - int totalTries = Conf::config.getMutexRetries(); - while (tries < totalTries) - { - rv = OK; - firstNode= (IndexNode*) hIdxNodeChunk->allocate(tbl->db_, &rv); - if (firstNode !=NULL) break; - if (rv != ErrLockTimeOut) - { - printError(rv, "Unable to allocate hash index node"); - return rv; - } - tries++; - } - if (firstNode == NULL){ - printError(rv, "Unable to allocate hash index node after %d retry", tries); - return rv; - } - firstNode->ptrToKey_ = keyPtr; - firstNode->ptrToTuple_ = tuple; - firstNode->next_ = NULL; - if (0 != Mutex::CASL((long*)&bucket->bucketList_, 0, (long)firstNode)) { - printError(ErrLockTimeOut, "Hash Index bucket lock timeout.. retry"); - hIdxNodeChunk->free(tbl->db_, firstNode); - return ErrLockTimeOut; - } - - printDebug(DM_HashIndex, "HashIndex insert new node %x in empty bucket", bucket->bucketList_); - } - else - { - BucketList list(head); - rc = list.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); - if (rc !=OK) { - printError(rc, "unable to insert into bucketlist rv:%d", rc); - return rc; - } - - } - if (!loadFlag) { - rc = tr->appendLogicalHashUndoLog(tbl->sysDB_, InsertHashIndexOperation, &hInfo, sizeof(HashUndoLogInfo)); - if (rc !=OK) - { - printError(rc, "Unable to append logical log before rc:%d", rc); - BucketList list(head); - DbRetVal rv = list.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); - //bucket->bucketList_ = list.getBucketListHead(); - if (rv == SplCase) { - printError(ErrWarning, "SplCase occured"); - if (0 != Mutex::CASL((long*)&bucket->bucketList_, - (long)bucket->bucketList_, (long)list.getBucketListHead())) { - printError(ErrSysFatal, "Double failure, may lead to hash node leak\n"); - } - }else if (rv !=OK) printError(ErrSysFatal, "double failure on undo log insert followed by hash bucket list remove\n"); - } - } - return rc; -} - - -DbRetVal HashIndex::remove(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool loadFlag) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - - HashIndexInfo *info = (HashIndexInfo*) indInfo; - DataType type = info->type; - int offset = info->fldOffset; - int noOfBuckets = info->noOfBuckets; - - ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); - Bucket* buckets = (Bucket*)citer.nextElement(); - - void *keyPtr =(void*)((char*)tuple + offset); - int bucket = 0; - if (type == typeComposite) { - char *keyBuffer = (char*) malloc(info->compLength); - memset(keyBuffer, 0, info->compLength); - void *keyStartBuffer = keyBuffer; - FieldIterator iter = info->idxFldList.getIterator(); - while(iter.hasElement()) - { - FieldDef *def = iter.nextElement(); - keyPtr = (char *)tuple + def->offset_; - if (def->type_ != typeVarchar) { - AllDataType::copyVal(keyBuffer, keyPtr, def->type_, - def->length_); - } else { - void *ptr = (void *) *(long *) keyPtr; - if (ptr) - AllDataType::copyVal(keyBuffer, ptr, def->type_, - def->length_); - } - keyBuffer = keyBuffer + AllDataType::size(def->type_,def->length_); - } - bucket = HashIndex::computeHashBucket(type, keyStartBuffer, noOfBuckets, info->compLength); - ::free(keyStartBuffer); - } - else { - if (type != typeVarchar) - bucket = HashIndex::computeHashBucket(type, keyPtr, noOfBuckets, - info->compLength); - else { - void *ptr = (void *) *(long *) keyPtr; - if (ptr) - bucket = HashIndex::computeHashBucket(type, ptr, noOfBuckets, - info->compLength); - else bucket = 0; - } - } - - Bucket *bucket1 = &buckets[bucket]; - HashUndoLogInfo hInfo; - hInfo.metaData_ = tbl->db_->getMetaDataPtr(); - hInfo.bucket_ = bucket1; - hInfo.tuple_ = tuple; - hInfo.hChunk_ = ((CINDEX *)indexPtr)->hashNodeChunk_; - hInfo.keyPtr_ = keyPtr; - - IndexNode *head = (IndexNode*) bucket1->bucketList_; - - if (!head) { printError(ErrNotExists, "Hash index does not exist:should never happen\n"); - return ErrNotExists; - } - BucketList list(head); - printDebug(DM_HashIndex, "Removing hash index node from head %x", head); - - DbRetVal rc = list.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); - if (SplCase == rc) - { - printDebug(DM_HashIndex, "Removing hash index node from head "); - //bucket1->bucketList_ = list.getBucketListHead(); - if (0 != Mutex::CASL((long*)&bucket1->bucketList_, - (long)head, (long)list.getBucketListHead())) { - printError(ErrSysFatal, "Lock time out for hash bucket. retry\n"); - return ErrLockTimeOut; - } - rc = OK; - } - if (!loadFlag) { - rc =tr->appendLogicalHashUndoLog(tbl->sysDB_, DeleteHashIndexOperation, &hInfo, sizeof(HashUndoLogInfo)); - if (rc !=OK) - { - rc = list.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); - if (rc !=OK) printError(ErrSysFatal, "double failure on undo log remove followed by hash bucket list insert\n"); - //bucket1->bucketList_ = list.getBucketListHead(); - if (0 != Mutex::CASL((long*)&bucket1->bucketList_, - (long)bucket1->bucketList_, (long)list.getBucketListHead())) { - printError(ErrSysFatal, "Double failure on index insert"); - } - } - } - return rc; -} - -DbRetVal HashIndex::update(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool loadFlag) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - - HashIndexInfo *info = (HashIndexInfo*) indInfo; - DataType type = info->type; - int offset = info->fldOffset; - int noOfBuckets = info->noOfBuckets; - - //check whether the index key is updated or not - //if it is not updated return from here - void *keyPtr =(void*)((char*)tuple + offset); - char *kPtr= (char*)keyPtr; - - //creating old key value buffer for composite primary keys - char *oldKeyBuffer = (char*) malloc(info->compLength); - memset(oldKeyBuffer, 0, info->compLength); - void *oldKeyStartBuffer = oldKeyBuffer; - FieldIterator iter = info->idxFldList.getIterator(); - while(iter.hasElement()) { - FieldDef *def = iter.nextElement(); - keyPtr = (char *)tuple + def->offset_; - AllDataType::copyVal(oldKeyBuffer, keyPtr, def->type_, def->length_); - oldKeyBuffer = oldKeyBuffer + AllDataType::size(def->type_, def->length_); - } - - keyPtr = (void *) kPtr; - //Iterate through the bind list and check - FieldIterator idxFldIter = info->idxFldList.getIterator(); - char *keyBindBuffer ; - if(type==typeBinary) { - keyBindBuffer = (char*) malloc(2 * info->compLength); - memset(keyBindBuffer, 0, 2 * info->compLength); - } else { - keyBindBuffer = (char*) malloc(info->compLength); - memset(keyBindBuffer, 0, info->compLength); - } - void *keyStartBuffer = (void*) keyBindBuffer; - bool keyUpdated = false; - - while (idxFldIter.hasElement()) { - FieldDef *idef = idxFldIter.nextElement(); - FieldIterator fldIter = tbl->fldList_.getIterator(); - while (fldIter.hasElement()) { - FieldDef *def = fldIter.nextElement(); - if (0 == strcmp(def->fldName_, idef->fldName_)) { - if (NULL != def->bindVal_) { - if(type==typeBinary) { - AllDataType::copyVal(keyBindBuffer, def->bindVal_, - def->type_, 2*def->length_); - keyStartBuffer=calloc(1,info->compLength); - AllDataType::convertToBinary(keyStartBuffer, keyBindBuffer, typeString, info->compLength); - free(keyBindBuffer); - } else { - AllDataType::copyVal(keyBindBuffer, def->bindVal_, - def->type_, def->length_); - keyBindBuffer = keyBindBuffer + AllDataType::size(def->type_, def->length_); - } - } else { - AllDataType::copyVal(keyBindBuffer, (char *) tuple + def->offset_, def->type_, def->length_); - keyBindBuffer = keyBindBuffer + AllDataType::size(def->type_, def->length_); - } - keyUpdated = true; - break; - } - } - } - if (!keyUpdated) { - //printf("DEBUG::key not updated\n"); - free(keyStartBuffer); - free(oldKeyStartBuffer); - return OK; - } - //printf("DEBUG::it is wrong coming here\n"); - bool result = false; - if (type == typeComposite) - result = AllDataType::compareVal(oldKeyStartBuffer, keyStartBuffer, - OpEquals, info->type, info->compLength); - else result = AllDataType::compareVal(keyPtr, keyStartBuffer, - OpEquals, info->type, info->compLength); - if (result) { - free(keyStartBuffer); - free(oldKeyStartBuffer); - return OK; - } - printDebug(DM_HashIndex, "Updating hash index node: Key value is updated"); - - ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); - - Bucket* buckets = (Bucket*)citer.nextElement(); - - //remove the node whose key is updated - int bucketNo = 0; - if (type == typeComposite) - bucketNo = computeHashBucket(type, oldKeyStartBuffer, noOfBuckets, info->compLength); - else bucketNo = computeHashBucket(type, keyPtr, noOfBuckets, info->compLength); - printDebug(DM_HashIndex, "Updating hash index node: Bucket for old value is %d", bucketNo); - Bucket *bucket = &buckets[bucketNo]; - - HashUndoLogInfo *hInfo1 = new HashUndoLogInfo(); - hInfo1->metaData_ = tbl->db_->getMetaDataPtr(); - hInfo1->bucket_ = bucket; - hInfo1->tuple_ = tuple; - hInfo1->hChunk_ = ((CINDEX *)indexPtr)->hashNodeChunk_; - hInfo1->keyPtr_ = keyPtr; - - //it may run into deadlock, when two threads updates tuples which falls in - //same buckets.So take both the mutex one after another, which will reduce the - //deadlock window. - int ret = bucket->mutex_.getLock(tbl->db_->procSlot); - if (ret != 0) - { - delete hInfo1; - free(keyStartBuffer); - free(oldKeyStartBuffer); - printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",bucketNo); - return ErrLockTimeOut; - } - //insert node for the updated key value - int newBucketNo = computeHashBucket(type, - keyStartBuffer, noOfBuckets, info->compLength); - printDebug(DM_HashIndex, "Updating hash index node: Bucket for new value is %d", newBucketNo); - - Bucket *bucket1 = &buckets[newBucketNo]; - HashUndoLogInfo *hInfo2 = new HashUndoLogInfo(); - hInfo2->metaData_ = tbl->db_->getMetaDataPtr(); - hInfo2->bucket_ = bucket; - hInfo2->tuple_ = tuple; - hInfo2->hChunk_ = ((CINDEX *)indexPtr)->hashNodeChunk_; - hInfo2->keyPtr_ = keyPtr; - bucket1->mutex_.getLock(tbl->db_->procSlot); - if (ret != 0) - { - delete hInfo1; - delete hInfo2; - free(keyStartBuffer); - free(oldKeyStartBuffer); - printError(ErrLockTimeOut,"Unable to acquire bucket Mutex for bucket %d",newBucketNo); - return ErrLockTimeOut; - } - - IndexNode *head1 = (IndexNode*) bucket->bucketList_; - if (head1) - { - BucketList list1(head1); - printDebug(DM_HashIndex, "Updating hash index node: Removing node from list with head %x", head1); - list1.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); - bucket->bucketList_=list1.getBucketListHead(); - } - else - { - printError(ErrSysInternal,"Update: Bucket list is null"); - bucket1->mutex_.releaseLock(tbl->db_->procSlot); - bucket->mutex_.releaseLock(tbl->db_->procSlot); - delete hInfo1; - delete hInfo2; - free(keyStartBuffer); - free(oldKeyStartBuffer); - return ErrSysInternal; - } - DbRetVal rc = OK; - if (!loadFlag) { - rc = tr->appendLogicalHashUndoLog(tbl->sysDB_, DeleteHashIndexOperation, hInfo1, sizeof(HashUndoLogInfo)); - if (rc !=OK) - { - BucketList list((IndexNode*) bucket->bucketList_); - rc = list.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); - if (rc !=OK) printError(ErrSysFatal, "double failure on undo log remove followed by hash bucket list insert\n"); - bucket->bucketList_ = list.getBucketListHead(); - bucket1->mutex_.releaseLock(tbl->db_->procSlot); - bucket->mutex_.releaseLock(tbl->db_->procSlot); - delete hInfo1; - delete hInfo2; - free(keyStartBuffer); - free(oldKeyStartBuffer); - return rc; - } - } - IndexNode *head2 = (IndexNode*) bucket1->bucketList_; - //Note:: the tuple will be in the same address location - //so not changing the keyptr and tuple during append - //only bucket where this node resides will only change - //if the index key is updated. - if (!head2) - { - DbRetVal rv = OK; - IndexNode *firstNode= (IndexNode*)(((Chunk*)iptr->hashNodeChunk_)->allocate(tbl->db_, &rv)); - if (firstNode == NULL) - { - printError(rv, "Error in allocating hash node"); - bucket1->mutex_.releaseLock(tbl->db_->procSlot); - bucket->mutex_.releaseLock(tbl->db_->procSlot); - delete hInfo1; - delete hInfo2; - free(keyStartBuffer); - free(oldKeyStartBuffer); - return rv; - } - firstNode->ptrToKey_ = keyPtr; - firstNode->ptrToTuple_ = tuple; - firstNode->next_ = NULL; - bucket1->bucketList_ = (IndexNode*)firstNode; - printDebug(DM_HashIndex, "Updating hash index node: Adding new node %x:Head is empty", firstNode); - } - else - { - BucketList list2(head2); - printDebug(DM_HashIndex, "Updating hash index node: Adding node to list with head %x", head2); - list2.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); - bucket1->bucketList_ = list2.getBucketListHead(); - } - if (!loadFlag) { - - rc = tr->appendLogicalHashUndoLog(tbl->sysDB_, InsertHashIndexOperation, hInfo2, sizeof(HashUndoLogInfo)); - if (rc !=OK) - { - //reverting back the changes:delete new node and add the old - //node + remove logical undo log of the DeleteHashIndexOperation - BucketList list1((IndexNode*) bucket->bucketList_); - BucketList list2((IndexNode*) bucket1->bucketList_); - list1.insert((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr, tuple); - list2.remove((Chunk*)iptr->hashNodeChunk_, tbl->db_, keyPtr); - bucket->bucketList_ = list1.getBucketListHead(); - bucket1->bucketList_ = list2.getBucketListHead(); - UndoLogInfo *logInfo = tr->popUndoLog(); - Chunk *chunk = tbl->sysDB_->getSystemDatabaseChunk(UndoLogTableID); - chunk->free(tbl->sysDB_, logInfo); - } - } - bucket1->mutex_.releaseLock(tbl->db_->procSlot); - bucket->mutex_.releaseLock(tbl->db_->procSlot); - delete hInfo1; - delete hInfo2; - free(keyStartBuffer); - free(oldKeyStartBuffer); - return rc; -} - -//Following three methods are used to undo Logical Hash Indexes -DbRetVal HashIndex::insertLogicalUndoLog(Database *sysdb, void *data) -{ - HashUndoLogInfo *info = (HashUndoLogInfo *) data; - Chunk *hChunk = (Chunk *) info->hChunk_; - Database db; - db.setMetaDataPtr((DatabaseMetaData *) info->metaData_); - db.setProcSlot(sysdb->procSlot); - IndexNode *head = (IndexNode *)((Bucket *)info->bucket_)->bucketList_; - BucketList list(head); - DbRetVal rv = list.insert(hChunk, &db, info->keyPtr_, info->tuple_); - if (rv != OK) - { - printError(ErrLockTimeOut, "Unable to add to bucket..retry\n"); - return ErrLockTimeOut; - } - //((Bucket *)info->bucket_)->bucketList_ = list.getBucketListHead(); - if (0 != Mutex::CASL((long*)& (((Bucket *)info->bucket_)->bucketList_), - (long)(((Bucket *)info->bucket_)->bucketList_), - (long)list.getBucketListHead())) - { - printError(ErrLockTimeOut, "Unable to add to bucket..retry\n"); - return ErrLockTimeOut; - } - return OK; -} - -DbRetVal HashIndex::deleteLogicalUndoLog(Database *sysdb, void *data) -{ - HashUndoLogInfo *info = (HashUndoLogInfo *) data; - Chunk *hChunk = (Chunk *) info->hChunk_; - Database db; - db.setMetaDataPtr((DatabaseMetaData *)info->metaData_); - db.setProcSlot(sysdb->procSlot); - IndexNode *head = (IndexNode *)((Bucket *)info->bucket_)->bucketList_; - BucketList list(head); - DbRetVal rc = list.remove(hChunk, &db, info->keyPtr_); - //((Bucket *)info->bucket_)->bucketList_ = list.getBucketListHead(); - if (SplCase == rc) { - if (0 != Mutex::CASL((long*)& (((Bucket *)info->bucket_)->bucketList_), - (long)(((Bucket *)info->bucket_)->bucketList_), - (long)list.getBucketListHead())) - { - printError(ErrLockTimeOut, "Unable to set the head of hash index bucket\n"); - return ErrLockTimeOut; - } - }else if (rc != OK) { - printError(ErrLockTimeOut, "Unable to remove hash index node"); - return ErrLockTimeOut; - } - return OK; -} diff --git a/src/storage/Index.cxx b/src/storage/Index.cxx deleted file mode 100644 index afe1868a..00000000 --- a/src/storage/Index.cxx +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * 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 - -HashIndex* Index::hIdx = NULL; -TreeIndex* Index::tIdx = NULL; -TrieIndex* Index::iIdx = NULL; -long Index::usageCount = 0; - -Index* Index::getIndex(IndexType type) -{ - if (type == hashIndex) - { - if (NULL == hIdx) hIdx = new HashIndex(); - return hIdx; - }else if (type == treeIndex) { - if (NULL == tIdx) tIdx = new TreeIndex(); - return tIdx; - }else if (type == trieIndex) { - if (NULL == iIdx) iIdx = new TrieIndex(); - return iIdx; - } - return NULL; -} -void Index::destroy() -{ - usageCount--; - if(!usageCount) { - if(!hIdx) { delete hIdx; hIdx=NULL; } - if(!tIdx) { delete tIdx; tIdx=NULL; } - if(!iIdx) { delete tIdx; iIdx=NULL; } - } -} - diff --git a/src/storage/JoinTableImpl.cxx b/src/storage/JoinTableImpl.cxx deleted file mode 100644 index 1312472a..00000000 --- a/src/storage/JoinTableImpl.cxx +++ /dev/null @@ -1,689 +0,0 @@ -/*************************************************************************** - * 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 - -JoinTableImpl::JoinTableImpl() -{ - isNestedLoop= true; - pred = NULL; - curTuple = NULL; - leftTableHdl = NULL; - rightTableHdl = NULL; - isLeftRecOver = false; - isFirstCall = true; - availableLeft = true; - isFirstFetch = true; - isReturnNull = false; - //isOuterJoin = false; - isOptimized = false; - leftSideFail = false; - jType = INNER_JOIN; - isNestedLoop = true; - rightExhausted = false; -} -JoinTableImpl::~JoinTableImpl() {} - -DbRetVal JoinTableImpl::bindFld(const char *fldname, void *val, bool dummy) -{ - FieldInfo *info = new FieldInfo(); - char tableName[IDENTIFIER_LENGTH]; - char fieldName[IDENTIFIER_LENGTH]; - getTableNameAlone((char*)fldname, tableName); - getFieldNameAlone((char*)fldname, fieldName); - ListIterator iter = projList.getIterator(); - JoinProjFieldInfo *elem; - while (iter.hasElement()) - { - elem = (JoinProjFieldInfo*) iter.nextElement(); - if (strcmp(elem->fieldName, fieldName)==0 && - strcmp(elem->tableName, tableName) ==0) - { - printError(ErrBadCall, "Field already binded %s\n", fldname); - delete info; - return ErrBadCall; - } - if (strcmp(elem->fieldName, fieldName)==0 && - strcmp(elem->tableName, "") ==0) - { - printError(ErrBadCall, "Field already binded %s\n", fldname); - delete info; - return ErrBadCall; - } - } - JoinProjFieldInfo *def = new JoinProjFieldInfo(); - strcpy(def->tableName, tableName); - strcpy(def->fieldName, fieldName); - strcpy(def->tabFieldName, fldname); - if (strcmp (tableName, "") == 0) - getQualifiedName(fldname, def->tabFieldName); - def->appBuf = val; - DbRetVal rv = getFieldInfo(fldname, info); - if ( OK != rv) { - printError(ErrBadCall, "Field not found or unqualified field name %s", fldname); - delete def; - delete info; - return ErrSyntaxError; - } - def->bindBuf = AllDataType::alloc(info->type, info->length); - if (availableLeft) - leftTableHdl->bindFld(fldname, def->bindBuf); - else - rightTableHdl->bindFld(fldname, def->bindBuf); - def->type = info->type; - def->length= info->length; - projList.append(def); - delete info; - return OK; -} - -DbRetVal JoinTableImpl::optimize() -{ - PredicateImpl* predImpl = (PredicateImpl*) pred; - if (NULL != predImpl && !predImpl->isNotOrInvolved()) - { - //printf("not or or not involved\n"); - PredicateImpl *tblPred = NULL; - bool isPushed = false; - while (true) - { - tblPred = predImpl->getTablePredicate(); - if (NULL == tblPred) break; - if (pred == tblPred) - { - pred = NULL; - isPushed = pushPredicate(tblPred); - if (!isPushed) - { - //printf("optimizer could not push table predicate\n"); - } - break; - } - isPushed = pushPredicate(tblPred); - if (!isPushed) - { - //printf("optimizer could not push table predicate\n"); - } - } - while (true) - { - tblPred = predImpl->getJoinPredicate(); - if (pred == tblPred) - { - break; - } - if (NULL == tblPred) break; - isPushed = pushPredicate(tblPred); - if (!isPushed) - { - //printf("optimizer could not push join predicate\n"); - } - } - } - if (pred != NULL) - { - //push predicates leave the predicate nodes empty - //here we remove all the unnecessary nodes - predImpl = (PredicateImpl*) pred; - predImpl->removeIfNotNecessary(); - PredicateImpl *p = predImpl->getIfOneSidedPredicate(); - if (NULL != p) - { - //TODO::fix this leak below..it dumps core if uncommented - //delete pred; - pred = p; - predImpl = p; - } - if (predImpl->isDummyPredicate()) - { - //TODO::fix this leak below..it dumps core if uncommented - //delete pred; - pred = NULL; - } - } - DbRetVal rv = leftTableHdl->optimize(); - if (OK != rv) { - printError(ErrUnknown, "Left handle optimize failed"); - return rv; - } - rv = rightTableHdl->optimize(); - if (OK != rv) { - printError(ErrUnknown, "Left handle optimize failed"); - return rv; - } - optimizeRestrict(); - return OK; -} -void JoinTableImpl::optimizeRestrict() -{ - ScanType lType = leftTableHdl->getScanType(); - ScanType rType = rightTableHdl->getScanType(); - bool interChange = false; - if (lType == fullTableScan && rType != fullTableScan) interChange = true; - else if (lType != hashIndexScan && rType == treeIndexScan) interChange=true; - /* - if (interChange) { - Table *tmp = leftTableHdl; - leftTableHdl=rightTableHdl; - rightTableHdl = tmp; - }*/ - - //get the predicate with right table handle name - //rightTableHdl->getIndexType(); - return; -} -ScanType JoinTableImpl::getScanType() -{ - ScanType lType = leftTableHdl->getScanType(); - ScanType rType = rightTableHdl->getScanType(); - if (lType == hashIndexScan || rType == hashIndexScan) return hashIndexScan; - if (lType == treeIndexScan || rType == treeIndexScan) return treeIndexScan; - return fullTableScan; -} - -void JoinTableImpl::printPlan(int space) -{ - char spaceBuf[IDENTIFIER_LENGTH]; - memset(spaceBuf, 32, IDENTIFIER_LENGTH); - spaceBuf[space] = '\0'; - PredicateImpl* predImpl = (PredicateImpl*) pred; - printf("%s \n", spaceBuf); - if (jType == INNER_JOIN) - printf("%s INNER_JOIN \n", spaceBuf); - else if (jType == LEFT_JOIN) - printf("%s LEFT_JOIN \n", spaceBuf); - else if (jType == RIGHT_JOIN) - printf("%s RIGHT_JOIN \n", spaceBuf); - else if (jType == FULL_JOIN) - printf("%s FULL_JOIN \n", spaceBuf); - - if (predImpl) predImpl->print(space); - printf("%s \n", spaceBuf); - leftTableHdl->printPlan(space+2); - printf("%s \n", spaceBuf); - printf("%s \n", spaceBuf); - rightTableHdl->printPlan(space+2); - printf("%s \n", spaceBuf); - printf("%s \n", spaceBuf); -} - -DbRetVal JoinTableImpl::execute() -{ - //if (!leftTableHdl->getName()) printf("execute called with isFirstCall %d\n", isFirstCall); - PredicateImpl* predImpl = (PredicateImpl*) pred; - isNestedLoop = true; - if (pred) - { - predImpl->setProjectionList(&projList); - predImpl->solveForProjList(this); - } - //push the table scan predicates - //PRABA::TEMP: - //if( jType != LEFT_JOIN) optimize(); - if (leftTableHdl->getName()) { - //printf("left execute call %s", leftTableHdl->getName()); - if (!isOptimized) { optimize(); isOptimized = true; } - leftTableHdl->execute(); - leftTableHdl->fetch(); - }else if (isFirstCall) { - //printf("First call"); - if (!isOptimized) { optimize(); isOptimized = true; } - leftTableHdl->execute(); - void *rec = leftTableHdl->fetch(); - //printf("rec value is %x\n", rec); - isFirstCall = false; - } - rightTableHdl->execute(); - TableImpl *tImpl = (TableImpl*) rightTableHdl; - //isOuterJoin= true; - isFirstFetch = true; - return OK; -} - -void* JoinTableImpl::fetch() -{ - //if (!leftTableHdl->getName()) printf("fetch called\n"); - if (isLeftRecOver) return NULL; - void * rec = fetchInt(); - //if (!leftTableHdl->getName()) printf("rec got %x\n", rec); - - if (rec == NULL && jType == LEFT_JOIN && isFirstFetch) - { - isFirstFetch= false; - isReturnNull = true; - copyValuesToBindBuffer(NULL); - //if (!leftTableHdl->getName()) printf("rec value is 0x1\n"); - return (void*)0x1; - } - isReturnNull = false; - //if (!leftTableHdl->getName()) printf("rec value is %x\n", rec); - return rec; -} - -void* JoinTableImpl::fetchInt() -{ - PredicateImpl* predImpl = (PredicateImpl*) pred; - DbRetVal rv = OK; - if (isNestedLoop) - { - void *rec = rightTableHdl->fetch(); - if (rec==NULL) - { - return fetchRightFail(); - } - else { - if (jType == LEFT_JOIN && leftSideFail - && !leftTableHdl->getName() - && !isFirstFetch) return fetchRightFail(); - - bool result = true; - while (true) { - if (pred) rv = predImpl->evaluate(result); - if ( rv !=OK && rv !=ErrNullValues ) return NULL; - if (result) break; - rec = rightTableHdl->fetch(); - if (rec == NULL) { - if (jType == LEFT_JOIN && isFirstFetch) return NULL; - return fetchInt(); - } - } - copyValuesToBindBuffer(NULL); - isFirstFetch = false; - return rec; - } - } - return NULL; -} - -void* JoinTableImpl::fetchRightFail() -{ - if (jType == LEFT_JOIN && isFirstFetch) { return NULL;} - //if (!leftTableHdl->getName()) printf("fetch right fail called\n"); - PredicateImpl* predImpl = (PredicateImpl*) pred; - DbRetVal rv = OK; - rightTableHdl->closeScan(); - void *rec = leftTableHdl->fetch(); - //if (!leftTableHdl->getName()) printf("rec value is %x\n", rec); - leftSideFail= false; - if (rec == NULL) {isLeftRecOver= true; return NULL;} - else if (rec == (char*)0x1) { leftSideFail = true;} - rightTableHdl->execute(); - isFirstFetch = true; - rec = rightTableHdl->fetch(); - if (rec == NULL || leftSideFail) { - //if(!leftTableHdl->getName()) printf("RIGHT FETCH returns NULL\n"); - //if join condition(pred) is set and if it is pushed to tablehdl - //when there is index, it returns no record - if (jType == LEFT_JOIN && pred) return NULL; - return fetchRightFail(); - } - bool result = true; - isReturnNull = false; - while (true) { - if (pred) rv = predImpl->evaluate(result); - if ( OK != rv) return NULL; - if (result) { break; } - rec = rightTableHdl->fetch(); - if (rec == NULL) { - if (jType == LEFT_JOIN) { - //return from here so that null values for rhs table will be set - return (void*) NULL; - } - return fetchInt(); - } - } - isFirstFetch = false; - copyValuesToBindBuffer(NULL); - return rec; -} - -void* JoinTableImpl::fetch(DbRetVal &rv) -{ - rv = OK; - return fetchInt(); -} - -void* JoinTableImpl::fetchNoBind() -{ - printError(ErrBadCall, "fetchNoBind not implemented for JoinTableImpl"); - return NULL; -} - -void* JoinTableImpl::fetchNoBind(DbRetVal &rv) -{ - rv = OK; - return fetchNoBind(); -} - -DbRetVal JoinTableImpl::copyValuesToBindBuffer(void *elem) -{ - //Iterate through the bind list and copy the value here - ListIterator fIter = projList.getIterator(); - JoinProjFieldInfo *def; - while (fIter.hasElement()) - { - def = (JoinProjFieldInfo*) fIter.nextElement(); - if (NULL != def->appBuf) { - AllDataType::copyVal(def->appBuf, def->bindBuf, def->type, def->length); - } - } - return OK; -} -DbRetVal JoinTableImpl::getQualifiedName(const char *fldname, char *qualName) -{ - if (leftTableHdl != NULL) - leftTableHdl->getQualifiedName(fldname, qualName); - if (rightTableHdl != NULL) - rightTableHdl->getQualifiedName(fldname, qualName); - return OK; -} - -DbRetVal JoinTableImpl::getFieldInfo(const char* fldname, FieldInfo *&info) -{ - DbRetVal retCode = OK, retCode1 =OK; - availableLeft = false; - retCode = leftTableHdl->getFieldInfo(fldname, info); - if (retCode ==OK) - { - availableLeft= true; - //return OK; - } - retCode1 = rightTableHdl->getFieldInfo(fldname, info); - if (retCode1 ==OK) - { - if (availableLeft) return ErrSyntaxError; - return OK; - } - return retCode; -} - -long JoinTableImpl::numTuples() -{ - return 0; -} - -DbRetVal JoinTableImpl::closeScan() -{ - //if (leftTableHdl && leftTableHdl->getName()) leftTableHdl->closeScan(); - if (leftTableHdl) leftTableHdl->closeScan(); - if (rightTableHdl) rightTableHdl->closeScan(); - isLeftRecOver = false; - isFirstCall = true; - return OK; - -} - -DbRetVal JoinTableImpl::close() -{ - closeScan(); - if (leftTableHdl) { leftTableHdl->close(); leftTableHdl = NULL; } - if (rightTableHdl) { rightTableHdl->close(); rightTableHdl = NULL; } - ListIterator iter = projList.getIterator(); - JoinProjFieldInfo *elem; - while (iter.hasElement()) - { - elem = (JoinProjFieldInfo*) iter.nextElement(); - free(elem->bindBuf); - delete elem; - } - projList.reset(); - //delete pred; - ListIterator pIter = predList.getIterator(); - while(pIter.hasElement()) - { - PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement(); - delete pImpl; - } - predList.reset(); - delete this; - return OK; -} - -void* JoinTableImpl::getBindFldAddr(const char *name) -{ - void* bindAddr = leftTableHdl->getBindFldAddr(name); - if (bindAddr) return bindAddr; - return rightTableHdl->getBindFldAddr(name); -} - -List JoinTableImpl::getFieldNameList() -{ - List fldNameList; - - List leftList = leftTableHdl->getFieldNameList(); - ListIterator lIter = leftList.getIterator(); - while (lIter.hasElement()) - { - Identifier *elem = (Identifier*) lIter.nextElement(); - fldNameList.append(elem); - } - - List rightList = rightTableHdl->getFieldNameList(); - ListIterator rIter = rightList.getIterator(); - while (rIter.hasElement()) - { - Identifier *elem = (Identifier*) rIter.nextElement(); - fldNameList.append(elem); - } - leftList.reset(); - rightList.reset(); - return fldNameList; -} - -bool JoinTableImpl::isTableInvolved(char *tableName) -{ - //printf("isTableInvolved called in join for %s\n", tableName); - bool isInvolved = leftTableHdl->isTableInvolved(tableName); - if (isInvolved) return true; - isInvolved = rightTableHdl->isTableInvolved(tableName); - return isInvolved; -} - -void* JoinTableImpl::getBindedBuf(char* tName, char* fName) -{ - ListIterator iter = projList.getIterator(); - JoinProjFieldInfo *elem; - while (iter.hasElement()) - { - elem = (JoinProjFieldInfo*) iter.nextElement(); - if (strcmp(elem->fieldName, fName)==0 && - strcmp(elem->tableName, tName) ==0) - { - return elem->bindBuf; - } - } - return NULL; -} - -bool JoinTableImpl::pushPredicate(Predicate *pr) -{ - //printf("PRABA::pushPredicate called\n"); - PredicateImpl *pImpl = (PredicateImpl*) pr; - bool pushed = leftTableHdl->pushPredicate(pr); - if (!pushed) - { - pushed = rightTableHdl->pushPredicate(pr); - } - if (!pushed) - { - //printf("PRABA::unable to push the predicate\n"); - //TODO::check if needs to be placed here - char *lTbl = leftTableHdl->getName(); - char *rTbl = rightTableHdl->getName(); - char *lAliasTbl = leftTableHdl->getAliasName(); - char *rAliasTbl = rightTableHdl->getAliasName(); - bool isAliasSet = lAliasTbl && rAliasTbl && (!(strcmp(lAliasTbl,"") == 0 && strcmp(rAliasTbl,"") == 0 )); - char fullName[IDENTIFIER_LENGTH]; - char lTabName[IDENTIFIER_LENGTH]; - char rTabName[IDENTIFIER_LENGTH]; - char lFldName[IDENTIFIER_LENGTH]; - char rFldName[IDENTIFIER_LENGTH]; - strcpy(fullName, pImpl->getFldName1()); - Table::getTableNameAlone(fullName, lTabName); - Table::getFieldNameAlone(fullName, lFldName); - strcpy(fullName, pImpl->getFldName2()); - Table::getTableNameAlone(fullName, rTabName); - Table::getFieldNameAlone(fullName, rFldName); - - if (NULL != lTbl && NULL != rTbl) - { - //both size TableImpl handles are there - if (0 == strcmp(lTbl, lTabName) || 0 == strcmp(lTbl, rTabName) || ( isAliasSet && (0 == strcmp(lAliasTbl, lTabName) ||0 == strcmp(lAliasTbl,rTabName))) ) - { - if (0 == strcmp(rTbl, lTabName) || 0 == strcmp(rTbl, rTabName)|| (isAliasSet && (0 == strcmp(rAliasTbl, lTabName) ||0 == strcmp(rAliasTbl,rTabName)))) - { - //printf("PRABA::pushed join predicate here1\n"); - //PRABA::START - ComparisionOp op = pImpl->getCompOp(); - if (0 == strcmp(rTbl, rTabName) ||(isAliasSet && 0 == strcmp(rAliasTbl, rTabName))) - { - //bool ind = rightTableHdl->hasIndex(rFldName); - if (OpEquals ==op) { - void *buf = getBindedBuf(lTabName, lFldName); - rightTableHdl->addPredicate(rFldName, op, buf); - pImpl->setDontEvaluate(); - } - }else if (0==strcmp(rTbl, lTabName) || (isAliasSet && 0== strcmp(rAliasTbl, lTabName))) - { - //bool ind = rightTableHdl->hasIndex(lFldName); - if (OpEquals ==op) { - void *buf = getBindedBuf(rTabName, rFldName); - rightTableHdl->addPredicate(lFldName, op, buf); - pImpl->setDontEvaluate(); - } - } - //PRABA::END - setPredicate(pr); - pushed = true; - } - } - }else{ - if(isTableInvolved(lTabName) && isTableInvolved(rTabName)) - { - //printf("PRABA::pushed join predicate here2\n"); - //PRABA::START - ComparisionOp op = pImpl->getCompOp(); - if (strcmp(rTbl, rTabName) ==0) - { - //bool ind = rightTableHdl->hasIndex(rFldName); - if (OpEquals ==op) { - void *buf = getBindedBuf(lTabName, lFldName); - rightTableHdl->addPredicate(rFldName, op, buf); - pImpl->setDontEvaluate(); - } - }else if (strcmp(rTbl, lTabName) ==0) - { - //bool ind = rightTableHdl->hasIndex(lFldName); - if (OpEquals ==op) { - void *buf = getBindedBuf(rTabName, rFldName); - rightTableHdl->addPredicate(lFldName, op, buf); - pImpl->setDontEvaluate(); - } - } - //PRABA::END - setPredicate(pr); - pushed = true; - } - } - } - return pushed; -} - -void JoinTableImpl::setPredicate(Predicate *pr) -{ - if (NULL == pred) { pred = pr; return; } - Predicate *curPred = pred; - PredicateImpl *newPred = new PredicateImpl(); - newPred->setTerm(curPred, OpAnd, pr); - newPred->setProjectionList(&projList); - predList.append(newPred); - pred = newPred; - return; -} - -bool JoinTableImpl::isFldNull(const char *name) -{ - bool ret = false; - if(NULL==leftTableHdl->getName()) - { - ret = leftTableHdl->isFldNull(name); - if(ret==true) return true; - } - else - { - char tableName[IDENTIFIER_LENGTH]; - Table::getTableNameAlone((char*)name, tableName); - if(0 == strcmp(tableName,leftTableHdl->getName())) - { - return leftTableHdl->isFldNull(name); - } - } - if(NULL==rightTableHdl->getName()) - { - if (isReturnNull) return true; - ret = rightTableHdl->isFldNull(name); - if(ret==true) return true; - } - else{ - char tableName[IDENTIFIER_LENGTH]; - Table::getTableNameAlone((char*)name, tableName); - if(0==strcmp(tableName,rightTableHdl->getName())) - { - if (isReturnNull) return true; - return rightTableHdl->isFldNull(name); - } - } - return ret; -} - -//same as above expect it does not check for isRecordFound flag -//as it is set only after predicate evaluate -bool JoinTableImpl::isFldNullInt(const char *name) -{ - bool ret = false; - if(NULL==leftTableHdl->getName()) - { - ret = leftTableHdl->isFldNull(name); - if(ret==true) return true; - } - else - { - char tableName[IDENTIFIER_LENGTH]; - Table::getTableNameAlone((char*)name, tableName); - if(0 == strcmp(tableName,leftTableHdl->getName())) - { - return leftTableHdl->isFldNull(name); - } - } - if(NULL==rightTableHdl->getName()) - { - ret = rightTableHdl->isFldNull(name); - if(ret==true) return true; - } - else{ - char tableName[IDENTIFIER_LENGTH]; - Table::getTableNameAlone((char*)name, tableName); - if(0==strcmp(tableName,rightTableHdl->getName())) - { - return rightTableHdl->isFldNull(name); - } - } - return ret; -} - diff --git a/src/storage/OrderByTree.cxx b/src/storage/OrderByTree.cxx deleted file mode 100644 index b443c843..00000000 --- a/src/storage/OrderByTree.cxx +++ /dev/null @@ -1,133 +0,0 @@ -/*************************************************************************** - * 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 - -//Used for float type field and individual order by clause -void OrderByTree::insertSpecialCaseDataNode(void *data) -{ - if(dataNode.size() == 0){ dataNode.append(data); return;} - ListIterator iter = dataNode.getIterator(); - ListIterator fldIter = orderByList.getIterator(); - iter.reset(); - int ret=0; - void *insertedData = NULL; - void *prevIter = iter.getCurrentListNode(); - void *prev = prevIter; - bool shouldInsertHappenAtMiddle=false; - OrderByFldDef *oFldDef = NULL; - int offset=0; - char *fldData=NULL, *fldInsertData=NULL; - bool result=false; - while (iter.hasElement()) - { - bool shoudInsertHere=false; - bool isPrevEqual=false; - offset=0; - insertedData = iter.nextElement(); - fldIter.reset(); - while (fldIter.hasElement()) - { - oFldDef = (OrderByFldDef*) fldIter.nextElement(); - fldData = ((char*)data)+offset; - fldInsertData = ((char*)insertedData)+offset; - offset += oFldDef->length; - result=AllDataType::compareVal(fldData, fldInsertData, OpEquals,oFldDef->type, oFldDef->length); - if(result) - { - shoudInsertHere = true; - isPrevEqual = true; - continue; - } - else - { - result=AllDataType::compareVal(fldData, fldInsertData, OpGreaterThan,oFldDef->type, oFldDef->length); - if(result) - { - if(oFldDef->isDesc) - { - shoudInsertHere = true; - isPrevEqual = false; - continue; - } - else{ - if(shoudInsertHere && !isPrevEqual) { isPrevEqual = false; continue;} - shoudInsertHere=false; break; - } - }else - { - //dataisDesc) - { - shoudInsertHere = true; - isPrevEqual = false; - continue; - } - else{ - if(shoudInsertHere && !isPrevEqual ) { isPrevEqual = false; continue;} - shoudInsertHere=false; break; - } - } - } - }//inner while ends here - if(shoudInsertHere){ - if(shouldInsertHappenAtMiddle) - dataNode.addAtMiddle(data, prevIter); - else - dataNode.addAtBegin(data); - return; - } - prevIter = prev; - prev = iter.getCurrentListNode(); - shouldInsertHappenAtMiddle=true; - } - dataNode.append(data); -} - -DbRetVal OrderByTree::insertDataNode(void *data) -{ - if(!fullOrderBy) { - insertSpecialCaseDataNode(data); - return OK; - } - dataNode.append(data); - projMap.insert(data); - return OK; -} - -bool OrderByTree::find(void *data) -{ - void *element = projMap.find(data); - if (element) return true; - return false; -} - -int OrderByTree::compare(void *element1,void *element2,int size) -{ - return os::memcmp(element1,element2,size); -} - -ListIterator OrderByTree::getListIterator() -{ - return dataNode.getIterator(); -} - -void OrderByTree::removeAll() -{ - dataNode.reset(); - if(fullOrderBy) projMap.removeAll(); - return; -} diff --git a/src/storage/OrderTableImpl.cxx b/src/storage/OrderTableImpl.cxx deleted file mode 100644 index fe184c44..00000000 --- a/src/storage/OrderTableImpl.cxx +++ /dev/null @@ -1,468 +0,0 @@ -/*************************************************************************** - * 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 -OrderTableImpl::OrderTableImpl() -{ - tableHdl = NULL; - curTuple = NULL; - sortTree.setDistinct(false); - nullValues = 0; - orderBySize =0; - projSize =0; - orderBindBuf= NULL; - orderBuffer = NULL; - isPlanCreated=false; -} - -OrderTableImpl::~OrderTableImpl() -{ - //free memory allocated. make sure that field buffers are freed only once. - //for stmts which has more than one agg on same field needs to be handled safely - closeScan(); - - ListIterator oiter = fldOrderByList.getIterator(); - OrderByFldDef *elem = NULL; - while (oiter.hasElement()) - { - elem = (OrderByFldDef*) oiter.nextElement(); - if(!elem->alreadyBinded) free(elem->bindBuf); - delete elem; - } - fldOrderByList.reset(); - - if (tableHdl != NULL) tableHdl->close(); - tableHdl = NULL; - if (orderBuffer) ::free(orderBuffer); -} - -void *OrderTableImpl::getBindFldAddr(const char *name) -{ - printError(ErrBadCall, "OrderTableImpl getBindFldAdddr not implemented\n"); - return NULL; -} - -DbRetVal OrderTableImpl::bindFld(const char *name, void *val, bool dummy) -{ - printError(ErrBadCall, "OrderTableImpl bindFld not implemented\n"); - return ErrBadCall; -} - -DbRetVal OrderTableImpl::setOrderBy(const char *fldname, bool isDesc) -{ - FieldInfo *info = new FieldInfo(); - DbRetVal rv = tableHdl->getFieldInfo(fldname, info); - if (OK !=rv) { delete info; return rv; } - OrderByFldDef *orderFld=new OrderByFldDef(); - strcpy(orderFld->fldName, fldname); - orderFld->type = info->type; - //orderFld->length = info->length; - orderFld->length = os::align(AllDataType::size(info->type, info->length)); - orderFld->bindBuf = NULL; - orderFld->isDesc = isDesc; - - ListIterator iter = fldProjList.getIterator(); - FieldValue *elem; - - while (iter.hasElement()) - { - elem = (FieldValue*) iter.nextElement(); - if ((NULL != tableHdl->getName() && - NULL != strstr(elem->fldName, fldname) || - NULL != strstr(fldname, elem->fldName)) || - strcmp(elem->fldName, fldname)==0) - { - orderFld->bindBuf = elem->value; - orderFld->alreadyBinded = true; - break; - } - } - if (!orderFld->bindBuf) - { - orderFld->bindBuf = AllDataType::alloc(orderFld->type, orderFld->length); - rv = tableHdl->bindFld(fldname, orderFld->bindBuf); - if (rv != OK) { - delete info; - ::free(orderFld->bindBuf); - delete orderFld; - return rv; - } - } - - //if underlying tablehandle is TableImpl, then set isNull - orderFld->isNull = true; - if (info->isNull) orderFld->isNull = false; - if (info->isPrimary || info->isDefault || info->isAutoIncrement) { - orderFld->isNull = true; - } - if (NULL == tableHdl->getName()) orderFld->isNull=false; - - - fldOrderByList.append(orderFld); - delete info; - return OK; -} - -OrderByType OrderTableImpl::getOrderType() -{ - ListIterator oiter = fldOrderByList.getIterator(); - OrderByFldDef *oFldDef = NULL; - bool isDescending = false; - bool firstIter = true; - while (oiter.hasElement()) - { - oFldDef = (OrderByFldDef*) oiter.nextElement(); - if(firstIter) { - firstIter= false; - isDescending = oFldDef->isDesc; - continue; - } - if (oFldDef->isDesc != isDescending) { isDescending = false; break; } - } - if(isDescending) return Desc; else return Asc; -} - -void OrderTableImpl::checkAndSetSortAlgorithm() -{ - if (sortTree.getDistinct()) sortTree.setFullOrderBy(); - sortTree.setOrderByList(fldOrderByList); - - //set orderby size - orderBySize = computeOrderBySize(); - sortTree.setKeySize(orderBySize + sizeof(int)); - - //set proj size - projSize = 0; - ListIterator iter = fldProjList.getIterator(); - FieldValue *fValue; - while (iter.hasElement()) - { - fValue = (FieldValue*) iter.nextElement(); - projSize = projSize + os::align(fValue->length); - } - OrderByFldDef *ordFld=NULL; - bool optGrpIntNoNull= false; - if (orderBySize == sizeof(int)) - { - ListIterator iter = fldOrderByList.getIterator(); - ordFld = (OrderByFldDef*)iter.nextElement(); - if (!ordFld->isNull && ordFld->type == typeInt) - { - optGrpIntNoNull=true; - orderBindBuf = ordFld->bindBuf; - sortTree.setOrdIntNoNull(); - } - } - return; -} - -DbRetVal OrderTableImpl::execute() -{ - nullValues = 0; - tableHdl->execute(); - if (!isPlanCreated) { - checkAndSetSortAlgorithm(); - setNullableForProj(); - if (sortTree.getDistinct()) - { - orderBuffer = (char*)malloc(orderBySize + sizeof(int)); - } - isPlanCreated=true; - } - void *tuple = NULL; - while ((tuple = tableHdl->fetch()) != NULL) - { - if (sortTree.getDistinct()) insertDistinct(); else insert(); - } - sortIter = sortTree.getListIterator(); - return OK; -} - -int OrderTableImpl::computeOrderBySize() -{ - ListIterator oiter = fldOrderByList.getIterator(); - OrderByFldDef *oFldDef = NULL; - int nodeOffset =0; - while (oiter.hasElement()) - { - oFldDef = (OrderByFldDef*) oiter.nextElement(); - nodeOffset = nodeOffset + os::align(oFldDef->length); - } - return nodeOffset; -} - -DbRetVal OrderTableImpl::insertDistinct() -{ - char *elem = orderBuffer; - memset(orderBuffer, 0, orderBySize + sizeof(int)); - ListIterator oiter = fldOrderByList.getIterator(); - OrderByFldDef *oFldDef = NULL; - int orderNullValues =0; - int nodeOffset =0; - int i=0; - while ((oFldDef = (OrderByFldDef*) oiter.nextElement()) != NULL) - { - if (oFldDef->isNull && tableHdl->isFldNull(oFldDef->fldName)) - SETBIT(orderNullValues, i); - else - AllDataType::copyVal(elem+nodeOffset, oFldDef->bindBuf, - oFldDef->type, oFldDef->length); - nodeOffset = nodeOffset + os::align(oFldDef->length); - i++; - } - AllDataType::copyVal(elem+nodeOffset, &orderNullValues, typeInt, - sizeof(orderNullValues)); - if (sortTree.find(elem)) return OK; - nodeOffset = nodeOffset+ sizeof(orderNullValues); - - int nodeSize = orderBySize + projSize; - nodeSize = nodeSize + sizeof(int);//to store order by field null values - nodeSize = nodeSize + sizeof(nullValues);//to store proj field null values - char *element = (char*)malloc(nodeSize); - memcpy(element, elem, orderBySize + sizeof(int)); - nullValues = 0; - i=0; - ListIterator iter = fldProjList.getIterator(); - FieldValue *fValue = NULL; - void* ptrToCopyNullValues = element+nodeOffset; - nodeOffset = nodeOffset + sizeof(nullValues); - while ((fValue = (FieldValue*) iter.nextElement()) != NULL) - { - if (fValue->isNullable && tableHdl->isFldNull(fValue->fldName)) - SETBIT(nullValues, i); - else - AllDataType::copyVal(element+nodeOffset, fValue->value, - fValue->type, fValue->length); - nodeOffset = nodeOffset + fValue->length; - i++; - } - AllDataType::copyVal(ptrToCopyNullValues, &nullValues, typeLongLong, - sizeof(nullValues)); - DbRetVal rv = sortTree.insertDataNode(element); - return rv; -} - -DbRetVal OrderTableImpl::insert() -{ - //compute size of projection - int nodeSize = orderBySize + projSize; - nodeSize = nodeSize + sizeof(int);//to store order by field null values - nodeSize = nodeSize + sizeof(nullValues);//to store proj field null values - char *element = (char*)malloc(nodeSize); - //copy values - int nodeOffset =0; - ListIterator oiter = fldOrderByList.getIterator(); - OrderByFldDef *oFldDef = NULL; - int orderNullValues =0; - int i=0; - while ((oFldDef = (OrderByFldDef*) oiter.nextElement()) != NULL) - { - //oFldDef = (OrderByFldDef*) oiter.nextElement(); - if (oFldDef->isNull && tableHdl->isFldNull(oFldDef->fldName)) - SETBIT(orderNullValues, i); - else - AllDataType::copyVal(element+nodeOffset, oFldDef->bindBuf, - oFldDef->type, oFldDef->length); - nodeOffset = nodeOffset + os::align(oFldDef->length); - i++; - } - AllDataType::copyVal(element+nodeOffset, &orderNullValues, typeInt, - sizeof(orderNullValues)); - nodeOffset = nodeOffset+ sizeof(orderNullValues); - nullValues = 0; - i=0; - ListIterator iter = fldProjList.getIterator(); - FieldValue *fValue = NULL; - void* ptrToCopyNullValues = element+nodeOffset; - nodeOffset = nodeOffset + sizeof(nullValues); - while ((fValue = (FieldValue*) iter.nextElement()) != NULL) - { - //fValue = (FieldValue*) iter.nextElement(); - if (fValue->isNullable && tableHdl->isFldNull(fValue->fldName)) - SETBIT(nullValues, i); - else - AllDataType::copyVal(element+nodeOffset, fValue->value, - fValue->type, fValue->length); - nodeOffset = nodeOffset + os::align(fValue->length); - i++; - } - AllDataType::copyVal(ptrToCopyNullValues, &nullValues, typeLongLong, - sizeof(nullValues)); - DbRetVal rv = sortTree.insertDataNode(element); - if (rv == ErrUnique) ::free (element); - return OK; -} - -void* OrderTableImpl::fetch() -{ - void *elem = sortIter.nextElement(); - if (NULL == elem) return NULL; - copyValuesToBindBuffer(elem); - return elem; - -} - -void* OrderTableImpl::fetch(DbRetVal &rv) -{ - rv = OK; - return fetch(); -} - -void* OrderTableImpl::fetchNoBind() -{ - void *elem = sortIter.nextElement(); - if (NULL == elem) return NULL; - copyValuesToBindBuffer(elem); - return elem; -} - -void* OrderTableImpl::fetchNoBind(DbRetVal &rv) -{ - rv = OK; - return fetchNoBind(); -} - -DbRetVal OrderTableImpl::setOrderByList(List oList) -{ - ListIterator fIter = oList.getIterator(); - FieldValue *def; - while (fIter.hasElement()) - { - def = (FieldValue*) fIter.nextElement(); - setOrderBy(def->fldName); - } - return OK; -} - -DbRetVal OrderTableImpl::copyValuesToBindBuffer(void *elem) -{ - //Iterate through the bind list and copy the value here - ListIterator fIter = fldProjList.getIterator(); - FieldValue *def; - char *colPtr= (char*) elem + orderBySize; - colPtr = colPtr + sizeof(int); - nullValues = *(long long*) colPtr; - colPtr = colPtr + sizeof (nullValues); - while (fIter.hasElement()) - { - def = (FieldValue*) fIter.nextElement(); - if (NULL != def->value) { - AllDataType::copyVal(def->value, colPtr, def->type, def->length); - colPtr = colPtr + os::align(def->length); - } - } - return OK; -} - -void OrderTableImpl::setNullableForProj() -{ - ListIterator fIter = fldProjList.getIterator(); - FieldValue *def; - FieldInfo *info = new FieldInfo(); - while (fIter.hasElement()) - { - def = (FieldValue*) fIter.nextElement(); - tableHdl->getFieldInfo(def->fldName, info); - def->isNullable = true; - if (info->isNull || info->isPrimary || - info->isDefault || info->isAutoIncrement) { - def->isNullable = false; - } - if (NULL == tableHdl->getName()) def->isNullable=true; - } - delete info; - return; -} - -bool OrderTableImpl::isFldNull(const char *fldName) -{ - int pos = 0; - ListIterator fIter = fldProjList.getIterator(); - FieldValue *def; - while (fIter.hasElement()) - { - def = (FieldValue*) fIter.nextElement(); - if (strcmp(fldName, def->fldName) == 0) { - break; - } - pos++; - } - return isFldNull(pos); -} - -bool OrderTableImpl::isFldNull(int projPos) -{ - if (BITSET(nullValues, projPos)) return true; - return false; -} - -long OrderTableImpl::numTuples() -{ - return tableHdl->numTuples(); -} - -DbRetVal OrderTableImpl::closeScan() -{ - sortIter.reset(); - ListIterator iter = sortTree.getListIterator(); - void *elem= NULL; - while(iter.hasElement()) { - elem = iter.nextElement(); - free(elem); - } - sortTree.removeAll(); - if (tableHdl) tableHdl->closeScan(); - return OK; -} - -DbRetVal OrderTableImpl::close() -{ - nullValues = 0; - closeScan(); - delete this; - return OK; -} - -void OrderTableImpl::printPlan(int space) -{ - char spaceBuf[IDENTIFIER_LENGTH]; - memset(spaceBuf, 32, IDENTIFIER_LENGTH); - spaceBuf[space] = '\0'; - printf("%s \n", spaceBuf); - printf("%s \n", spaceBuf); - ListIterator giter = fldOrderByList.getIterator(); - OrderByFldDef *fldDef=NULL; - while ((fldDef = (OrderByFldDef*)giter.nextElement()) != NULL) - { - if (fldDef->isDesc) \ - printf("%s %s DESC \n", spaceBuf, - fldDef->fldName); - else - printf("%s %s ASC \n", spaceBuf, - fldDef->fldName); - } - printf("%s \n", spaceBuf); - if (sortTree.getDistinct()) - printf("%s true \n", spaceBuf); - printf("%s \n", spaceBuf); - if (tableHdl) tableHdl->printPlan(space+2); - return; -} - diff --git a/src/storage/TableDef.cxx b/src/storage/TableDef.cxx deleted file mode 100644 index e6c12fa5..00000000 --- a/src/storage/TableDef.cxx +++ /dev/null @@ -1,142 +0,0 @@ -/*************************************************************************** - * 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 - -TableDef::~TableDef() -{ - reset(); -} - -void TableDef::reset() -{ - fldList.removeAll(); - fldCount = 0; -} - -int TableDef::addField(const char *name, DataType type, size_t length, - const void *defaultValue, bool notNull, bool autoIn) -{ - if (name == NULL) return (int)ErrBadArg; - if(strlen(name)>IDENTIFIER_LENGTH) - { - printError(ErrBadRange,"Field name should not exceed 64 character"); - return (int)ErrBadRange; - } - // The following code checks for duplicates - FieldIterator iter = getFieldIterator(); - while (iter.hasElement()) - { - FieldDef *def = iter.nextElement(); - if (! strcmp(def->fldName_, name)) { - printError(ErrAlready, "Field %s already Exists", name); - return (int) ErrAlready; - } - } - - if (!Util::isIdentifier((char*)name)) { - printError(ErrBadArg, "fieldname contains invalid characters"); - return (int) ErrBadArg; - } - FieldDef fldDef; - strcpy(fldDef.fldName_, name); - fldDef.fldName_[IDENTIFIER_LENGTH] = '\0'; - fldDef.type_ = type; - fldDef.length_ = AllDataType::size(type, length); - fldDef.bindVal_=NULL; - if (defaultValue != NULL && *(char *)defaultValue != '\0') - { - fldDef.isDefault_ = true; - if (typeBinary == type) { - const char *p = (const char *) defaultValue; - while (*p != '\0') { - if (! isxdigit((int)(*p++)) ) { - printError(ErrBadArg, "Invalid hexadecimal value"); - return (int) ErrBadArg; - } - } - } - os::memcpy(fldDef.defaultValueBuf_, defaultValue, DEFAULT_VALUE_BUF_LENGTH); - } - else - { - fldDef.isDefault_ = false; - os::memset(fldDef.defaultValueBuf_,0, DEFAULT_VALUE_BUF_LENGTH); - } - fldDef.isNull_ = notNull; - fldDef.isAutoIncrement_ = autoIn; - //os::memset(fldDef.autoVal_,0, DEFAULT_VALUE_BUF_LENGTH); - - /*PRABA:COMMENTED - switch(type) - { - case typeString : - case typeVarchar: - case typeBinary : - fldDef.length_ = os::align(length); - break; - default: - fldDef.length_ = os::align(AllDataType::size(type)); - break; - } - */ - if (type == typeBinary) fldDef.length_ = os::align(length); - fldDef.offset_ = fldList.getTupleSize(); - int ret = fldList.append(fldDef); - if (0 == ret) fldCount++; - return ret; -} - -int TableDef::dropField(const char *name) -{ - int ret = fldList.remove(name); - if (0 == ret) fldCount--; - return ret; -} - -int TableDef::getFieldCount() -{ - return fldCount; -} - -size_t TableDef::getTupleSize() -{ - size_t length = 0; - FieldIterator iter = getFieldIterator(); - while (iter.hasElement()) - { - FieldDef *def = iter.nextElement(); - if (def->type_ == typeVarchar) - length += sizeof (void *); - else if (def->type_ == typeString) - length += os::align(def->length_); - else - length = length + def->length_; - } - return length; -} - -bool TableDef::isVarcharPresentInSchema(FieldIterator &iter) -{ - while (iter.hasElement()) - { - FieldDef *fDef = iter.nextElement(); - if (fDef->type_ == typeVarchar) return true; - } - return false; -} diff --git a/src/storage/TableImpl.cxx b/src/storage/TableImpl.cxx deleted file mode 100644 index f8256dea..00000000 --- a/src/storage/TableImpl.cxx +++ /dev/null @@ -1,748 +0,0 @@ -/*************************************************************************** - * 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 //for AggType - -void Table::getFieldNameAlone(char *fname, char *name) { - bool dotFound= false; - char *fullname = fname; - while(*fullname != '\0') - { - if (*fullname == '.') { dotFound = true; break; } - fullname++; - } - if (dotFound) strcpy(name, ++fullname); else strcpy(name, fname); - -} - -void Table::getTableNameAlone(char *fname, char *name) { - strcpy(name, fname); - char *start = name; - bool dotFound = false; - while(*name != '\0') - { - if (*name == '.') { *name='\0'; dotFound = true; break; } - name++; - } - if (!dotFound) strcpy(start, ""); - return; -} -DbRetVal TableImpl::getQualifiedName(const char *fldname, char *qualName) -{ - FieldInfo *info = new FieldInfo(); - DbRetVal rv = getFieldInfo(fldname,info); - if (rv == OK) - sprintf(qualName, "%s.%s", getName(), fldname); - return rv; -} - - -DbRetVal TableImpl::bindFld(const char *name, void *val, bool isNullExpl) -{ - if (name[0] == '*' ) return OK; - //set it in the field list - char fieldName[IDENTIFIER_LENGTH]; - getFieldNameAlone((char*)name, fieldName); - DbRetVal rv = fldList_.updateBindVal(fieldName, val, isNullExpl); - if (OK != rv) { - printError(ErrNotExists, "Field %s does not exist", fieldName); - return rv; - } - return OK; -} - -int TableImpl::getFldPos(char *name) -{ - return fldList_.getFieldPosition(name); -} - -void TableImpl::setAliasName(char *name) -{ - strcpy(aliasName, name); -} - -bool TableImpl::hasIndex(char* fName) -{ - if (NULL == indexPtr_) return false; - for (int i =0; i < numIndexes_; i++) - { - HashIndexInfo* info = (HashIndexInfo*) idxInfo[i]; - FieldIterator iter = info->idxFldList.getIterator(); - if(iter.hasElement()) - { - FieldDef *def = iter.nextElement(); - if(strcmp(def->fldName_, fName) == 0) - if(!iter.hasElement())//neglet if it is composite index - return true; - } - } - return false; -} - -IndexType TableImpl::getIndexType(char *fName, int *pos) -{ - if (NULL == indexPtr_) return unknownIndex; - for (int i =0; i < numIndexes_; i++) - { - HashIndexInfo* info = (HashIndexInfo*) idxInfo[i]; - FieldIterator iter = info->idxFldList.getIterator(); - if(iter.hasElement()) - { - FieldDef *def = iter.nextElement(); - if(strcmp(def->fldName_, fName) == 0) - if(!iter.hasElement()) {//neglet if it is composite index - *(int*)pos = i; - return info->indType; - } - } - } - *(int*)pos = -1; - return unknownIndex; -} - -void TableImpl::addPredicate(char *fName, ComparisionOp op, void *buf) -{ - char fieldName[IDENTIFIER_LENGTH]; - Table::getFieldNameAlone(fName, fieldName); - PredicateImpl *pred = (PredicateImpl*) pred_; - PredicateImpl *newPred = new PredicateImpl(); - newPred->setTerm(fName, op, buf); - if (NULL == pred) { pred_ = newPred; predList.append(newPred); return; } - if (pred->isSingleTerm()) - { - bool res = pred->appendIfSameFld(fName, op, buf); - if(res) { - delete newPred; - return; - } - } - PredicateImpl *bothPred = new PredicateImpl(); - bothPred->setTerm(pred, OpAnd, newPred); - predList.append(bothPred); - pred_ = bothPred; -} - -DbRetVal TableImpl::trySharedLock(void *curTuple, Transaction **trans) -{ - DbRetVal lockRet = OK; - int tries = Conf::config.getMutexRetries(); - while((lockRet = lMgr_->getSharedLock(curTuple_, trans)) == ErrLockTimeOut) - { - tries--; - if (tries <=0) break; - } - return lockRet; -} - -DbRetVal TableImpl::tryExclusiveLock(void *curTuple, Transaction **trans) -{ - DbRetVal lockRet = OK; - int tries = Conf::config.getMutexRetries(); - while((lockRet = lMgr_->getExclusiveLock(curTuple_, trans)) == ErrLockTimeOut) - { - tries--; - if (tries <=0) break; - } - return lockRet; -} - -DbRetVal TableImpl::getCheckpointMutex() -{ - int tries=0; - DbRetVal rv = OK; - int totalTries = Conf::config.getMutexRetries(); - struct timeval timeout, timeval; - timeout.tv_sec = Conf::config.getMutexSecs(); - timeout.tv_usec = Conf::config.getMutexUSecs(); - - while (tries < totalTries) - { - rv = sysDB_->getSCheckpointMutex(); - if (OK == rv) break; - timeval.tv_sec = timeout.tv_sec; - timeval.tv_usec = timeout.tv_usec; - os::select(0,0,0,0,&timeval); - tries++; - } - if (tries == totalTries) { - printError(ErrLockTimeOut, "Checkpoint server is running. Retry after sometime."); - return ErrLockTimeOut; - } - return OK; -} - -void TableImpl::printInfo() -{ - printf(" %s \n", tblName_); - printf(" %d \n", numTuples()); - printf(" %d \n", pagesUsed()); - printf(" %d \n", spaceUsed()); - printf(" %d \n", numIndexes_); - printf(" %d \n", length_); - printf(" %d \n", numFlds_); - printf(" \n"); - for (int i =0; i %s \n", CatalogTableINDEX::getName(indexPtr_[i])); - printf(" \n"); - -} - -DbRetVal TableImpl::copyValuesFromBindBuffer(void *tuplePtr, bool isInsert) -{ - //Iterate through the bind list and copy the value here - FieldIterator fIter = fldList_.getIterator(); - char *colPtr = (char*) tuplePtr; - int fldpos=1; - while (fIter.hasElement()) - { - FieldDef *def = fIter.nextElement(); - if(def->isAutoIncrement_ && isInsert) - { - if (OK != takeTableMutex()) - { - printError(ErrLockTimeOut, - " Unable to take table mutex for increment key"); - return ErrLockTimeOut; - } - AllDataType::copyVal(&tempAutoVal,ptrToAuto, def->type_, def->length_); - if(def->bindVal_==NULL) - { - AllDataType::increment(colPtr, &tempAutoVal , def->type_); - AllDataType::copyVal(ptrToAuto,colPtr, def->type_, - def->length_); - colPtr = colPtr + def->length_; - fldpos++; - }else { - if(AllDataType::compareVal(def->bindVal_, &tempAutoVal, - OpGreaterThan, def->type_)) - { - AllDataType::copyVal(ptrToAuto,def->bindVal_, def->type_, - def->length_); - } - AllDataType::copyVal(colPtr, def->bindVal_, def->type_, - def->length_); - colPtr = colPtr + def->length_; - fldpos++; - } - releaseTableMutex(); - continue; - } - - if (def->isNull_ && !def->isDefault_ && NULL == def->bindVal_ && - isInsert) - { - printError(ErrNullViolation, - "NOT NULL constraint violation for field %s", def->fldName_); - return ErrNullViolation; - } - if (def->isDefault_ && NULL == def->bindVal_ && isInsert) - { - if (! def->isNullExplicit_) { - if (def->type_ == typeVarchar) { - DbRetVal rv = OK; - void *ptr = - ((Chunk *) vcChunkPtr_)->allocate(db_, def->length_, &rv); - *(long *)colPtr = (long)ptr; - AllDataType::convert(typeString, def->defaultValueBuf_, - def->type_, ptr, def->length_); - } else { - void *dest = AllDataType::alloc(def->type_, def->length_); - AllDataType::convert(typeString, def->defaultValueBuf_, - def->type_, dest, def->length_); - AllDataType::copyVal(colPtr, dest, def->type_, - def->length_); - free (dest); - } - } else { - setNullBit(fldpos); - *(long *) colPtr = 0L; - } - if (def->type_ != typeVarchar) colPtr = colPtr + def->length_; - else colPtr = colPtr + sizeof(void *); - fldpos++; - continue; - } - switch(def->type_) - { - case typeString: - if (NULL != def->bindVal_) - { - if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);} - // strncpy((char*)colPtr, (char*)def->bindVal_, def->length_); - // *(((char*)colPtr) + (def->length_-1)) = '\0'; - strcpy((char*)colPtr, (char*)def->bindVal_); - } - else if (!def->isNull_ && isInsert) setNullBit(fldpos); - colPtr = colPtr + def->length_; - break; - case typeBinary: - if (NULL != def->bindVal_ ) - { - if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);} - DbRetVal rv = AllDataType::strToValue(colPtr, - (char *) def->bindVal_, def->type_, def->length_); - if (rv != OK) return ErrBadArg; - } else if (!def->isNull_ && isInsert && !def->bindVal_) { - setNullBit(fldpos); - } - colPtr = colPtr + def->length_; - break; - case typeVarchar: - if (NULL != def->bindVal_) { - if (!isInsert && isFldNull(fldpos)) {clearNullBit(fldpos);} - DbRetVal rv = OK; - if (!isInsert) { - if (*(long *) colPtr != 0L) - ((Chunk *) vcChunkPtr_)->free(db_, - (void *)*(long *)colPtr); - *(long *) colPtr = 0L; - } - if (strcmp((char *)def->bindVal_,"") != 0) { - void *ptr = - ((Chunk *) vcChunkPtr_)->allocate(db_, - def->length_, &rv); - if (rv != OK) return ErrBadArg; - *(long *)colPtr = (long)ptr; - strcpy((char *)ptr, (char *)def->bindVal_); - } else { setNullBit(fldpos); } - } else if (!def->isNull_ && isInsert) setNullBit(fldpos); - colPtr = colPtr + sizeof(void *); - break; - default: - if (NULL != def->bindVal_) { - if(!isInsert && isFldNull(fldpos)){clearNullBit(fldpos);} - AllDataType::copyVal(colPtr, def->bindVal_, def->type_); - } else { if (!def->isNull_ && isInsert) setNullBit(fldpos); } - colPtr = colPtr + def->length_; - break; - } - fldpos++; - } - return OK; -} - - -DbRetVal TableImpl::copyValuesToBindBuffer(void *tuplePtr) -{ - //Iterate through the bind list and copy the value here - char *colPtr = (char*) tuplePtr; - FieldDef *def = NULL; - for (int i = 0; i < numBindFlds_; i++) { - def = (FieldDef *) bindListArray_[i]; - colPtr = (char *) tuplePtr + def->offset_; - if (def->type_ != typeVarchar) - AllDataType::copyVal(def->bindVal_, colPtr, def->type_, - def->length_); - else { - char *ptr = (char *) *(long *) colPtr; - if (ptr != NULL) strcpy((char *)def->bindVal_, ptr); - } - } - return OK; -} - -void TableImpl::printSQLIndexString(FILE *fp, int fd) -{ - if (fp == NULL) fp = stdout; - CatalogTableINDEXFIELD cIndexField(sysDB_); - char fName[IDENTIFIER_LENGTH]; - char idxName[IDENTIFIER_LENGTH]; - char *fldName = fName; - DataType type; - for (int i = 0; i < numIndexes_ ; i++) - { - CINDEX *iptr = (CINDEX*) indexPtr_[i]; - sprintf(idxName,"%s_idx_Auto_increment",getName()); - if(strcmp(iptr->indName_,idxName)==0){ continue; } - if (Conf::config.useDurability()) { - struct Object obj; - strcpy(obj.name, iptr->indName_); - if (iptr->indexType_ == hashIndex) { - obj.type = hIdx; - obj.bucketChunk = ((Chunk *)iptr->chunkPtr_)->getFirstPage(); - obj.firstPage = ((Chunk *)iptr->hashNodeChunk_)->getFirstPage(); - obj.curPage = ((Chunk *)iptr->hashNodeChunk_)->getCurrentPage(); - } else if (iptr->indexType_ == treeIndex) { - obj.type = tIdx; - obj.firstPage = ((Chunk *)iptr->chunkPtr_)->getFirstPage(); - obj.curPage = ((Chunk *)iptr->chunkPtr_)->getCurrentPage(); - long nodes = ((Chunk *)iptr->chunkPtr_)->getTotalDataNodes(); - if(nodes) { - ChunkIterator cIter = ((Chunk *)iptr->chunkPtr_)->getIterator(); - obj.bucketChunk = cIter.nextElement(); - } else obj.bucketChunk = NULL; - } - //TODO::Trie - void *buf = &obj; - write(fd, buf, sizeof(obj)); - } - fprintf(fp, "CREATE INDEX %s on %s ( ", iptr->indName_, getName()); - FieldList fldList; - cIndexField.getFieldInfo(iptr, fldList); - FieldIterator fIter = fldList.getIterator(); - bool firstFld = true; - while(fIter.hasElement()) - { - FieldDef *def = fIter.nextElement(); - if (firstFld) { fprintf(fp, " %s ", def->fldName_); firstFld = false; } - else fprintf(fp, " ,%s ", def->fldName_); - } - fldList.removeAll(); - fprintf(fp, " ) "); - - if (iptr->indexType_ == hashIndex) fprintf(fp, " HASH "); - else if (iptr->indexType_ == treeIndex) fprintf(fp, " TREE "); - else fprintf(fp, " TRIE "); - - HashIndexInfo* hInfo = (HashIndexInfo*)idxInfo[i]; - if (hInfo->isUnique) fprintf(fp, " UNIQUE"); - if(hInfo->noOfBuckets != 1009 && - hInfo->noOfBuckets !=0) fprintf(fp, " SIZE %d ",((HashIndexInfo*) idxInfo[i])->noOfBuckets ); - fprintf(fp, ";\n"); - } -} - - -void TableImpl::setTableInfo(char *name, int tblid, size_t length, - int numFld, int numIdx, void *chunk, void *vcchunk) -{ - strcpy(tblName_, name); - tblID_ = tblid; - length_ = length; - numFlds_ = numFld; - numIndexes_ = numIdx; - chunkPtr_ = chunk; - vcChunkPtr_ = vcchunk; -} - -long TableImpl::spaceUsed() -{ - Chunk *chk = (Chunk*)chunkPtr_; - long totSize = chk->getTotalDataNodes() * chk->getSize(); - totSize = totSize + (chk->totalPages() * sizeof (PageInfo)); - return totSize; -} - -int TableImpl::pagesUsed() -{ - Chunk *chk = (Chunk*)chunkPtr_; - return chk->totalPages(); -} - -List TableImpl::getFieldNameList() -{ - List fldNameList; - FieldIterator fIter = fldList_.getIterator(); - char fieldName[IDENTIFIER_LENGTH]; - while (fIter.hasElement()) - { - FieldDef *def = fIter.nextElement(); - Identifier *elem = new Identifier(); - Table::getFieldNameAlone(def->fldName_, fieldName); - sprintf(elem->name, "%s.%s", getName(), fieldName); - fldNameList.append(elem); - } - return fldNameList; -} - -DbRetVal TableImpl::close() -{ - if (iter) { iter->close(); delete iter; iter = NULL; } - TableImpl *fkTbl =NULL; - ListIterator tblIter = tblList.getIterator(); - tblIter.reset(); - while (tblIter.hasElement()){ - fkTbl = (TableImpl *) tblIter.nextElement(); - fkTbl->close(); - } - tblList.reset(); - tblIter = tblFkList.getIterator(); - tblIter.reset(); - while (tblIter.hasElement()){ - fkTbl = (TableImpl *) tblIter.nextElement(); - fkTbl->close(); - } - tblFkList.reset(); - printDebug(DM_Database,"Closing table handle: %x", this); - //table->unlock(); - //delete pred_; - ListIterator pIter = predList.getIterator(); - while (pIter.hasElement()) - { - PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement(); - delete pImpl; - } - predList.reset(); - delete this; - logFinest(Conf::logger, "Closing Table"); - return OK; -} - -DbRetVal TableImpl::takeTableMutex() -{ - struct timeval timeout, timeval; - timeout.tv_sec = Conf::config.getMutexSecs(); - timeout.tv_usec = Conf::config.getMutexUSecs(); - int tries=0; - int totalTries = Conf::config.getMutexRetries() *2; - int ret =0; - while (tries < totalTries) - { - ret = sysDB_->getAllocDatabaseMutex(); - if (ret == 0) break; - timeval.tv_sec = timeout.tv_sec; - timeval.tv_usec = timeout.tv_usec; - os::select(0, 0, 0, 0, &timeval); - tries++; - } - if (tries >= totalTries) return ErrLockTimeOut; - return OK; -} - -DbRetVal TableImpl::releaseTableMutex() -{ - sysDB_->releaseAllocDatabaseMutex(); - return OK; -} - -DbRetVal TableImpl::lock(bool shared) -{ - - DbRetVal ret = OK; -/* - if (shared) - ret = lMgr_->getSharedLock(chunkPtr_, NULL); - else - ret = lMgr_->getExclusiveLock(chunkPtr_, NULL); - if (OK != ret) - { - printError(ret, "Could not exclusive lock on the table %x", chunkPtr_); - }else { - //do not append for S to X upgrade - if (!ProcessManager::hasLockList.exists(chunkPtr_)) - ProcessManager::hasLockList.append(chunkPtr_); - } -*/ - return ret; -} - -DbRetVal TableImpl::unlock() -{ -/* - if (!ProcessManager::hasLockList.exists(chunkPtr_)) return OK; - DbRetVal ret = lMgr_->releaseLock(chunkPtr_); - if (OK != ret) - { - printError(ret, "Could not release exclusive lock on the table %x", chunkPtr_); - }else - { - ProcessManager::hasLockList.remove(chunkPtr_); - } -*/ - return OK; -} - -TableImpl::~TableImpl() -{ - if (NULL != iter ) { delete iter; iter = NULL; } - if (NULL != indexPtr_) { delete[] indexPtr_; indexPtr_ = NULL; } - if (NULL != idxInfo) - { - for (int i = 0; i < numIndexes_; i++) delete idxInfo[i]; - delete[] idxInfo; - idxInfo = NULL; - } - if (numFlds_ > 32 && cNullInfo != NULL) { - free(cNullInfo); cNullInfo = NULL; - } - if (bindList_.size()) bindList_.reset(); - if (bindListArray_) { free (bindListArray_); bindListArray_ = NULL; } - fldList_.removeAll(); - -} - -void *TableImpl::getBindFldAddr(const char *name) -{ - return fldList_.getBindField(name); -} - -bool TableImpl::isTableInvolved(char *tblName) -{ - //printf("Table isTableInvolved called for %s with %s\n", tblName, getName()); - if (0 == strcmp(getName(), tblName)) return true; else return false; -} - -void TableImpl::setCondition(Condition *p) -{ - isPlanCreated = false; - ListIterator pIter = predList.getIterator(); - while (pIter.hasElement()) - { - PredicateImpl *pImpl = (PredicateImpl*) pIter.nextElement(); - delete pImpl; - } - predList.reset(); - - if (p) pred_ = p->getPredicate(); else pred_ = NULL; -} - -void TableImpl::setPredicate(Predicate *pred) -{ - if (NULL == pred_) { pred_ = pred; return; } - - Predicate *curPred = pred_; - PredicateImpl *newPred = new PredicateImpl(); - newPred->setTerm(curPred, OpAnd, pred); - newPred->setTable(this); - pred_ = newPred; - return; -} - -void TableImpl::printPlan(int space) -{ - char spaceBuf[IDENTIFIER_LENGTH]; - memset(spaceBuf, 32, IDENTIFIER_LENGTH); - spaceBuf[space] = '\0'; - printf("%s \n", spaceBuf); - printf("%s %s \n", spaceBuf, getName()); - printf("%s %s \n", spaceBuf, ScanTypeNames[scanType_]); - PredicateImpl *pred = (PredicateImpl*)pred_; - if (pred) pred->print(space+2); - printf("%s \n", spaceBuf); -} - -void TableImpl::printSQLForeignString() -{ - DbRetVal rv=OK; - FieldNameList pkFieldList,fkFieldList; - void *tPkptr =NULL; - void *tFkptr = NULL; - void *chunkPk = NULL; - void *vcchunkPk = NULL; - CatalogTableTABLE cTable(sysDB_); - TableImpl *fkTbl =NULL; - ListIterator tblIter = tblList.getIterator(); - tblIter.reset(); - int firstFK=true; - while (tblIter.hasElement()){ - fkTbl = (TableImpl *) tblIter.nextElement(); - rv = cTable.getChunkAndTblPtr(fkTbl->getName(), chunkPk, tPkptr,vcchunkPk); - if ( OK != rv){return ;} - rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr, vcchunkPk); - if ( OK != rv){return ;} - CatalogTableFK cFk(sysDB_); - rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList); - if ( OK != rv){return;} - pkFieldList.resetIter(); - fkFieldList.resetIter(); - char *fldName = NULL; - bool firstField=true; - if(!firstFK) printf(", "); - printf(", FOREIGN KEY ( "); - while((fldName = fkFieldList.nextFieldName())!= NULL) - { - if (firstField) { - printf("%s",fldName); - firstField=false; - } - else - printf(",%s",fldName); - } - printf(" ) REFERENCES %s ( ",fkTbl->getName()); - firstField=true; - while((fldName = pkFieldList.nextFieldName())!= NULL) - { - if (firstField) { - printf("%s",fldName); - firstField=false; - } - else - printf(",%s",fldName); - } - printf(" )"); - firstFK=true; - pkFieldList.removeAll(); - fkFieldList.removeAll(); - } - return; -} - -DbRetVal TableImpl::compact() -{ - DbRetVal rv=OK; - int ret =((Chunk*)chunkPtr_)->compact(db_->procSlot); - if(ret!=0) return ErrLockTimeOut; - - if (NULL != vcChunkPtr_) { - ret = ((Chunk*)vcChunkPtr_)->compact(db_->procSlot); - if(ret!=0) return ErrLockTimeOut; - } - - if (NULL != indexPtr_) - { - int i; - //it has index - for (i = 0; i < numIndexes_ ; i++) - { - rv = compactIndexNode(indexPtr_[i]); - if (rv != OK) { - printError(rv, "Error in compacting index Node"); - break; - } - } - } - return rv; -} - -DbRetVal TableImpl::compactIndexNode( void *indexPtr) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - int ret1=0; - printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_); - if( hashIndex == (iptr->indexType_) ) - { - ret1 =((Chunk*)iptr->hashNodeChunk_)->compact(db_->procSlot); - if(ret1!=0){ - return ErrLockTimeOut; - } - }else if (treeIndex == (iptr->indexType_)) - { - ret1 =((Chunk*)iptr->chunkPtr_)->compact(db_->procSlot); - if(ret1!=0){ - return ErrLockTimeOut; - } - } else if ( trieIndex == (iptr->indexType_)) - { - ret1 =((Chunk*)iptr->chunkPtr_)->compact(db_->procSlot); - if(ret1!=0){ - return ErrLockTimeOut; - } - ret1 =((Chunk*)iptr->hashNodeChunk_)->compact(db_->procSlot); - if(ret1!=0){ - return ErrLockTimeOut; - } - } - return OK; -} diff --git a/src/storage/TableImplModifyOp.cxx b/src/storage/TableImplModifyOp.cxx deleted file mode 100644 index d57f3dba..00000000 --- a/src/storage/TableImplModifyOp.cxx +++ /dev/null @@ -1,885 +0,0 @@ -/*************************************************************************** - * 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 //for AggType - -bool TableImpl::isFldNull(const char *name){ - if (name[0] == '*') return false; - if ( strncasecmp(name,"COUNT",5) == 0 || strncasecmp(name,"AVG",3) == 0 || - strncasecmp(name,"MIN",3) == 0 || strncasecmp(name,"MAX",3) == 0 || - strncasecmp(name,"SUM",3) == 0 ) return false; - char fieldName[IDENTIFIER_LENGTH]; - getFieldNameAlone((char*)name, fieldName); - int colpos = fldList_.getFieldPosition(fieldName); - if (-1 == colpos) - { - printError(ErrNotExists, "Field %s does not exist", name); - return false; - } - - return isFldNull(colpos); -} - -bool TableImpl::isFldNull(int colpos) -{ - if (!curTuple_) return false; - if (colpos <1 || colpos > numFlds_) return false; - if (isIntUsedForNULL) { - int nullVal = *(int*)((char*)curTuple_ + (length_ - 4)); - if (BITSET(nullVal, colpos-1)) return true; - } - else { - char *nullOffset = (char*)curTuple_ + (length_ - os::align(numFlds_)); - if (nullOffset[colpos-1]) return true; - } - return false; -} - -void TableImpl::resetNullinfo() -{ - if (isIntUsedForNULL) { - iNullInfo =0; - } - else { - int i=0; - while(i < numFlds_) { cNullInfo[i++] = 0;} - } -} - -DbRetVal TableImpl::markFldNull(char const* name) -{ - DbRetVal rv = OK; - int colpos = fldList_.getFieldPosition(name); - if (-1 == colpos) - { - printError(ErrNotExists, "Field %s does not exist", name); - return ErrNotExists; - } - rv = markFldNull(colpos); - return rv; -} - -DbRetVal TableImpl::markFldNull(int fldpos) -{ - if (fldpos <1 || fldpos > numFlds_) return ErrBadArg; - if (isIntUsedForNULL) { - if (!BITSET(iNotNullInfo, fldpos-1)) SETBIT(iNullInfo, fldpos-1); - else { - printError(ErrNullViolation, "NOT NULL constraint violation"); - return ErrNullViolation; - } - } - else { - if (!cNotNullInfo[fldpos-1]) cNullInfo[fldpos-1] = 1; - else { - printError(ErrNullViolation, "NOT NULL constraint violation"); - return ErrNullViolation; - } - } - return OK; -} - -void TableImpl::clearFldNull(const char *name) -{ - int colpos = fldList_.getFieldPosition(name); - if (-1 == colpos) - { - printError(ErrNotExists, "Field %s does not exist", name); - return; - } - clearFldNull(colpos); -} - -void TableImpl::clearFldNull(int colpos) -{ - if (colpos <1 || colpos > numFlds_) return; - if (isIntUsedForNULL) CLEARBIT(iNullInfo, colpos-1); - else cNullInfo[colpos-1] = 0; - return; -} - -DbRetVal TableImpl::insertTuple() -{ - DbRetVal ret = getCheckpointMutex(); - if (ret !=OK) return ret; - void *tptr = NULL; - int tries=0; - int totalTries = Conf::config.getMutexRetries(); - while (tries < totalTries) - { - ret = OK; - tptr = ((Chunk*)chunkPtr_)->allocate(db_, &ret); - if (tptr !=NULL) break; - if (ret != ErrLockTimeOut) - { - sysDB_->releaseCheckpointMutex(); - printError(ret, "Unable to allocate record from chunk"); - return ret; - } - tries++; - } - if (NULL == tptr) - { - sysDB_->releaseCheckpointMutex(); - printError(ret, "Unable to allocate record from chunk after %d retries", tries); - return ret; - } - curTuple_ = tptr; - if(isFkTbl){ - TableImpl *fkTbl =NULL; - ListIterator tblIter = tblList.getIterator(); - tblIter.reset(); - while (tblIter.hasElement()){ - fkTbl = (TableImpl *) tblIter.nextElement(); - bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,true); - if(!pkRec){ - printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table"); - ((Chunk*)chunkPtr_)->free(db_, tptr); - sysDB_->releaseCheckpointMutex(); - return ErrForeignKeyInsert; - } - } - tblIter.reset(); - } - if (!loadFlag) { - //ret = lMgr_->getExclusiveLock(tptr, trans); - if (OK != tryExclusiveLock(tptr, trans)) - { - ((Chunk*)chunkPtr_)->free(db_, tptr); - printError(ret, "Could not get lock for the insert tuple %x", tptr); - sysDB_->releaseCheckpointMutex(); - return ErrLockTimeOut; - } - } - - ret = copyValuesFromBindBuffer(tptr); - if (ret != OK) - { - printError(ret, "Unable to copy values from bind buffer"); - if (!loadFlag) { - (*trans)->removeFromHasList(db_, tptr); - lMgr_->releaseLock(tptr); - } - - FieldIterator fIter = fldList_.getIterator(); - char *colPtr = (char*) curTuple_; - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - if (def->type_ == typeVarchar) { - char *ptr = (char *) *(long *) colPtr; - if (ptr != 0L) ((Chunk *) vcChunkPtr_)->free(db_, ptr); - } - } - ((Chunk*)chunkPtr_)->free(db_, tptr); - sysDB_->releaseCheckpointMutex(); - return ret; - } - int addSize = 0; - if (numFlds_ < 31) - { - addSize = 4; - *(int*)((char*)(tptr) + (length_-addSize)) = iNullInfo; - } - else - { - addSize = os::align(numFlds_); - os::memcpy(((char*)(tptr) + (length_-addSize)), cNullInfo, addSize); - - } - //int tupleSize = length_ + addSize; - if (NULL != indexPtr_) - { - int i; - //it has index - for (i = 0; i < numIndexes_ ; i++) - { - ret = insertIndexNode(*trans, indexPtr_[i], idxInfo[i], tptr); - if (ret != OK) { printError(ret, "Error in inserting to index %x", tptr); break;} - } - if ( ret != OK) - { - for (int j = 0; j < i ; j++) { - printError(ErrWarning, "Undo:Deleting index node"); - deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr); - } - if (!loadFlag) { - (*trans)->removeFromHasList(db_, tptr); - lMgr_->releaseLock(tptr); - } - - FieldIterator fIter = fldList_.getIterator(); - char *colPtr = (char*) curTuple_; - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - if (def->type_ == typeVarchar) { - char *ptr = (char *) *(long *) colPtr; - if (ptr != 0L) ((Chunk *) vcChunkPtr_)->free(db_, ptr); - } - } - ((Chunk*)chunkPtr_)->free(db_, tptr); - sysDB_->releaseCheckpointMutex(); - return ret; - } - } - if (!loadFlag) { - //TODO: number of varchar fields to be stored as a member in TableImpl - int nVarchars = 0; - FieldIterator fIter = fldList_.getIterator(); - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - if (def->type_ == typeVarchar) nVarchars++; - } - - // the undo log for insert should contain - // tuple ptr + metadata Ptr + no of varchars + ptrs to varchars for insert opearation - int size = (3 + nVarchars) * sizeof(void *) + sizeof(int); - void *data = malloc(size); - char *ptr = (char *)data; - *(long *) ptr = (long) tptr; ptr += sizeof(void *); - void *metaData = db_->getMetaDataPtr(); - *(long *) ptr = (long) metaData; ptr += sizeof(void *); - *(int *) ptr = nVarchars; ptr += sizeof(int); - *(long *) ptr = (long) vcChunkPtr_; ptr += sizeof(void *); - fIter = fldList_.getIterator(); - char *colPtr = (char*) curTuple_; - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - if (def->type_ == typeVarchar) { - *(long *) ptr = (long)colPtr; - ptr += sizeof(void *); - } - } - ret = (*trans)->appendUndoLog(sysDB_, InsertOperation, data, size); - ::free(data); - } - if (ret != OK) { - printError(ret, "Unable to create undo log for %x %d", tptr, *(int*)tptr); - for (int j = 0; j < numIndexes_ ; j++) { - printError(ErrWarning, "Deleting index node"); - deleteIndexNode(*trans, indexPtr_[j], idxInfo[j], tptr); - } - if (!loadFlag) { - (*trans)->removeFromHasList(db_, tptr); - lMgr_->releaseLock(tptr); - } - ((Chunk*)chunkPtr_)->free(db_, tptr); - } - sysDB_->releaseCheckpointMutex(); - return ret; -} - -DbRetVal TableImpl::deleteTuple() -{ - if (NULL == curTuple_) - { - printError(ErrNotOpen, "Scan not open: No Current tuple"); - return ErrNotOpen; - } - DbRetVal ret = getCheckpointMutex(); - if (ret != OK) return ret; - if(isPkTbl){ - TableImpl *fkTbl =NULL; - ListIterator tblIter = tblFkList.getIterator(); - tblIter.reset(); - while (tblIter.hasElement()){ - fkTbl = (TableImpl *) tblIter.nextElement(); - bool pkRec = isFkTableHasRecord(fkTbl->getName(),fkTbl); - if(pkRec){ - printError(ErrForeignKeyDelete, "A Relation Exists. Delete from child table first"); - sysDB_->releaseCheckpointMutex(); - return ErrForeignKeyDelete; - } - } - tblIter.reset(); - } - if (!loadFlag) { - //ret = lMgr_->getExclusiveLock(curTuple_, trans); - if (OK != tryExclusiveLock(curTuple_, trans)) - { - printError(ret, "Could not get lock for the delete tuple %x", - curTuple_); - sysDB_->releaseCheckpointMutex(); - return ErrLockTimeOut; - } - } - - if (NULL != indexPtr_) - { - int i; - //it has index - for (i = 0; i < numIndexes_ ; i++) - { - ret = deleteIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_); - if (ret != OK) break; - } - if (i != numIndexes_ ) - { - printError(ErrWarning, "Inserting back index node"); - for (int j = 0; j < i ; j++) - insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_); - if (!loadFlag) { - lMgr_->releaseLock(curTuple_); - (*trans)->removeFromHasList(db_, curTuple_); - } - printError(ret, "Unable to insert index node for tuple %x", curTuple_); - sysDB_->releaseCheckpointMutex(); - return ret; - } - } - if (!loadFlag) { - // the undo log for delete should contain - // tupleptr + metadataPtr + nVarchars + varchar chunk ptr + - // ptrs to varchars + size and value pairs for varchars - - //TODO: number of varchar fields to be stored as a member in TableImpl - void *tptr = curTuple_; - char *colPtr = (char *)curTuple_; - int nVarchars = 0; - int vcLenValPairSize = 0; - FieldIterator fIter = fldList_.getIterator(); - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - if (def->type_ == typeVarchar) { - nVarchars++; - if (* (long *) colPtr == 0L) - vcLenValPairSize = vcLenValPairSize + sizeof(int); - else vcLenValPairSize = vcLenValPairSize + sizeof(int) + - + os::align(strlen((char *) *(long *)colPtr) + 1); - } - } - int size = (3 + nVarchars) * sizeof(void *) + sizeof(int) - + vcLenValPairSize; - void *data = malloc(size); - char *ptr = (char *)data; - *(long *) ptr = (long) tptr; ptr += sizeof(void *); - void *metaData = db_->getMetaDataPtr(); - *(long *) ptr = (long) metaData; ptr += sizeof(void *); - *(int *) ptr = nVarchars; ptr += sizeof(int); - *(long *) ptr = (long) vcChunkPtr_; ptr += sizeof(void *); - fIter = fldList_.getIterator(); - colPtr = (char*) curTuple_; - char *valLenPairPtr = ptr + nVarchars * sizeof(void *); - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - int vcStrLen = 0; - if (def->type_ == typeVarchar) { - *(long *) ptr = (long )colPtr; ptr += sizeof(void *); - if (*(long *) colPtr == 0L) { - *(int *) valLenPairPtr = vcStrLen = 0; - valLenPairPtr += sizeof(int); - } else { - *(int *) valLenPairPtr = vcStrLen = - os::align(strlen((char *)*(long *)colPtr) + 1); - valLenPairPtr += sizeof(int); - strcpy(valLenPairPtr, (char *)*(long *)colPtr); - valLenPairPtr += vcStrLen; - } - } - } - ret = (*trans)->appendUndoLog(sysDB_, DeleteOperation, data, size); - ::free(data); - } - if (ret != OK) { - printError(ret, "Unable to create undo log for %x ", curTuple_); - for (int j = 0; j < numIndexes_ ; j++) { - printError(ErrWarning, "Inserting back index node"); - insertIndexNode(*trans, indexPtr_[j], idxInfo[j], curTuple_); - } - if (!loadFlag) { - (*trans)->removeFromHasList(db_, curTuple_); - lMgr_->releaseLock(curTuple_); - } - } - - FieldIterator fIter = fldList_.getIterator(); - char *colPtr = (char*) curTuple_; - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - if (def->type_ == typeVarchar) { - if (*(long *) colPtr != 0L) { - char *ptr = (char *) *(long *) colPtr; - ((Chunk *) vcChunkPtr_)->free(db_, ptr); - } - } - } - ((Chunk*)chunkPtr_)->free(db_, curTuple_); - iter->prev(); - sysDB_->releaseCheckpointMutex(); - return ret; -} - -int TableImpl::deleteWhere() -{ - DbRetVal ret = getCheckpointMutex(); - if (ret !=OK) return ret; - - int tuplesDeleted = 0; - DbRetVal rv = OK; - rv = execute(); - if (rv !=OK) { - sysDB_->releaseCheckpointMutex(); - return (int) rv; - } - while(true){ - fetchNoBind( rv); - if (rv != OK) { tuplesDeleted = (int)rv; break; } - if (NULL == curTuple_) break; - rv = deleteTuple(); - if (rv != OK) { - printError(rv, "Error: Could only delete %d tuples", tuplesDeleted); - closeScan(); - sysDB_->releaseCheckpointMutex(); - return (int) rv; - } - tuplesDeleted++; - } - closeScan(); - sysDB_->releaseCheckpointMutex(); - return tuplesDeleted; -} - -int TableImpl::truncate() -{ - //take exclusive lock on the table - //get the chunk ptr of the table - //traverse the tablechunks and free all the pages except the first one - //get the chunk ptr of all its indexes - //traverse the indexchunks and free all the pages except the first one - //release table lock - - //TEMPORARY FIX - DbRetVal rv = OK; - Predicate* tmpPred = pred_; - pred_ = NULL; - isPlanCreated = false; - int tuplesDeleted = deleteWhere(); - isPlanCreated = false; - pred_ = tmpPred; - return tuplesDeleted; -} - -DbRetVal TableImpl::updateTuple() -{ - if (NULL == curTuple_) - { - printError(ErrNotOpen, "Scan not open: No Current tuple"); - return ErrNotOpen; - } - DbRetVal ret = getCheckpointMutex(); - if (ret !=OK) return ret; - if(isFkTbl){ - TableImpl *fkTbl =NULL; - ListIterator tblIter = tblList.getIterator(); - tblIter.reset(); - while (tblIter.hasElement()){ - fkTbl = (TableImpl *) tblIter.nextElement(); - bool pkRec = isPkTableHasRecord(fkTbl->getName(),fkTbl,false); - if(!pkRec){ - printError(ErrForeignKeyInsert, "Unable to insert into foreign Key table.Check PK table"); - sysDB_->releaseCheckpointMutex(); - return ErrForeignKeyInsert; - } - } - tblIter.reset(); - } - - if (!loadFlag) { - //ret = lMgr_->getExclusiveLock(curTuple_, trans); - if (OK != tryExclusiveLock(curTuple_, trans)) - { - printError(ret, "Could not get lock for the update tuple %x", curTuple_); - sysDB_->releaseCheckpointMutex(); - return ErrLockTimeOut; - } - } - if (NULL != indexPtr_) - { - //it has index - //TODO::If it fails while updating index node, we have to undo all the updates - //on other indexes on the table.Currently it will leave the database in an - //inconsistent state. - for (int i = 0; i < numIndexes_ ; i++) - { - ret = updateIndexNode(*trans, indexPtr_[i], idxInfo[i], curTuple_); - if (ret != OK) - { - if (!loadFlag) { - lMgr_->releaseLock(curTuple_); - (*trans)->removeFromHasList(db_, curTuple_); - } - printError(ret, "Unable to update index node for tuple %x", curTuple_); - sysDB_->releaseCheckpointMutex(); - return ret; - } - } - } - - if (!loadFlag) { - // the undo log for update should contain - // tupleptr + tuple length + actual tuple + metadataPtr + - // nVarchars + varchar chunk ptr + ptrs to varchars + - // size and value pairs for varchars - - //TODO: number of varchar fields to be stored as a member in TableImpl - void *tptr = curTuple_; - char *colPtr = (char *)curTuple_; - int nVarchars = 0; - int vcLenValPairSize = 0; - FieldIterator fIter = fldList_.getIterator(); - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - if (def->type_ == typeVarchar) { - nVarchars++; - if (* (long *) colPtr == 0L) - vcLenValPairSize = vcLenValPairSize + sizeof(int); - else vcLenValPairSize = vcLenValPairSize + sizeof(int) + - + os::align(strlen((char *) *(long *)colPtr) + 1); - } - } - int size = (3 + nVarchars) * sizeof(void *) + 2 * sizeof(int) + - vcLenValPairSize + length_; - void *data = malloc(size); - char *ptr = (char *) data; - *(long *) ptr = (long) tptr; ptr += sizeof(void *); - *(int *) ptr = length_; ptr += sizeof(int); - os::memcpy(ptr, tptr, length_); ptr += length_; - void *metaData = db_->getMetaDataPtr(); - *(long *) ptr = (long) metaData; ptr += sizeof(void *); - *(int *) ptr = nVarchars; ptr += sizeof(int); - *(long *) ptr = (long) vcChunkPtr_; ptr += sizeof(void *); - fIter = fldList_.getIterator(); - colPtr = (char*) curTuple_; - char *valLenPairPtr = ptr + nVarchars * sizeof(void *); - while (fIter.hasElement()) { - FieldDef *def = fIter.nextElement(); - colPtr = (char *) curTuple_ + def->offset_; - int vcStrLen = 0; - if (def->type_ == typeVarchar) { - *(long *) ptr = (long)colPtr; ptr += sizeof(void *); - if (*(long *) colPtr == 0L) { - *(int *) valLenPairPtr = vcStrLen = 0; - valLenPairPtr += sizeof(int); - } else { - *(int *) valLenPairPtr = vcStrLen = - os::align(strlen((char *)*(long *)colPtr) + 1); - valLenPairPtr += sizeof(int); - strcpy(valLenPairPtr, (char *)*(long *)colPtr); - valLenPairPtr += vcStrLen; - } - } - } - ret = (*trans)->appendUndoLog(sysDB_, UpdateOperation, data, size); - ::free(data); - } - if (ret != OK) { - if (!loadFlag) { - lMgr_->releaseLock(curTuple_); - (*trans)->removeFromHasList(db_, curTuple_); - } - sysDB_->releaseCheckpointMutex(); - return ret; - } - - int addSize = 0; - int iNullVal=iNullInfo; - char *cNullVal = NULL; - if (numFlds_ > 32) { - addSize = os::align(numFlds_); - cNullVal = (char *) malloc(addSize); - os::memcpy(cNullVal, cNullInfo, addSize); - } - bool nullCharSet = false; - if (numFlds_ <= 32){ - addSize=4; - if (!iNullVal) - iNullInfo = *(int*)((char*)(curTuple_) + (length_- addSize)); - else - *(int*)((char*)(curTuple_) + (length_-addSize)) |= iNullInfo; - } else { - int i=0; - while(i < numFlds_) { - if(cNullInfo[i++]) { nullCharSet = true; break; } - } - char *null=(char*)(curTuple_) + (length_-addSize); - if (!nullCharSet) { - i=0; - while(i < numFlds_) { - if(null[i]) cNullInfo[i] = null[i]; - i++; - } - } else { - i = 0; - while(i < numFlds_) { - if(cNullInfo[i]) { null[i] |= cNullInfo[i]; } - i++; - } - } - } - DbRetVal rv = copyValuesFromBindBuffer(curTuple_, false); - if (rv != OK && !loadFlag) { - lMgr_->releaseLock(curTuple_); - (*trans)->removeFromHasList(db_, curTuple_); - sysDB_->releaseCheckpointMutex(); - return rv; - } - if (numFlds_ <= 32) { - if (!iNullVal) { - *(int*)((char*)(curTuple_) + (length_-addSize)) = iNullInfo; - iNullInfo=0; - } else iNullInfo=iNullVal; - } else { - int i = 0; - char *null=(char*)(curTuple_) + (length_-addSize); - if (!nullCharSet) { - os::memcpy(null, cNullInfo, addSize); - while (i < numFlds_) cNullInfo[i++] = 0; - } else os::memcpy(cNullInfo, cNullVal, addSize); - free(cNullVal); cNullVal = NULL; - } - sysDB_->releaseCheckpointMutex(); - return OK; -} - -long long TableImpl::getLastInsertedVal(DbRetVal &rv) -{ - rv=OK; - return *(long long*)ptrToAuto; -} - -void TableImpl::clearNullBit(int fldpos) -{ - if (fldpos <1 || fldpos > numFlds_) return; - if (isIntUsedForNULL) CLEARBIT(iNullInfo, fldpos-1); - else cNullInfo[fldpos-1] = 0; -} - -void TableImpl::setNullBit(int fldpos) -{ - if (fldpos <1 || fldpos > numFlds_) return; - if (isIntUsedForNULL) SETBIT(iNullInfo, fldpos-1); - else cNullInfo[fldpos-1] = 1; -} - - -//-1 index not supported -DbRetVal TableImpl::insertIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - DbRetVal ret = OK; - printDebug(DM_Table, "Inside insertIndexNode type %d", iptr->indexType_); - Index* idx = Index::getIndex(iptr->indexType_); - ret = idx->insert(this, tr, indexPtr, info, tuple,loadFlag); - return ret; -} - -DbRetVal TableImpl::deleteIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - DbRetVal ret = OK; - Index* idx = Index::getIndex(iptr->indexType_); - ret = idx->remove(this, tr, indexPtr, info, tuple, loadFlag); - return ret; -} - -DbRetVal TableImpl::updateIndexNode(Transaction *tr, void *indexPtr, IndexInfo *info, void *tuple) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - DbRetVal ret = OK; - Index* idx = Index::getIndex(iptr->indexType_); - //TODO::currently it updates irrespective of whether the key changed or not - //because of this commenting the whole index update code. relook at it and uncomment - - ret = idx->update(this, tr, indexPtr, info, tuple, loadFlag); - - return ret; -} - -bool TableImpl::isPkTableHasRecord(char *pkTableName, TableImpl *fkTbl,bool isInsert) -{ - DbRetVal rv=OK; - bool isRecExist=false; - FieldNameList pkFieldList,fkFieldList; - void *tPkptr =NULL; - void *tFkptr = NULL; - void *chunkPk = NULL; - void *vcchunkPk = NULL; - CatalogTableTABLE cTable(sysDB_); - rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tPkptr, vcchunkPk); - if ( OK != rv){return false;} - rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tFkptr, vcchunkPk); - if ( OK != rv){return false;} - CatalogTableFK cFk(sysDB_); - rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList); - if ( OK != rv){return false;} - int totFld = pkFieldList.size(); - Condition *condition = new Condition[totFld]; - char *pkFldName = NULL; - char *fkFldName = NULL; - FieldDef *def=NULL; - int i=0; - pkFieldList.resetIter(); - fkFieldList.resetIter(); - void *val=NULL; - while((pkFldName = pkFieldList.nextFieldName())!= NULL) - { - fkFldName = fkFieldList.nextFieldName(); - FieldIterator fIter = fldList_.getIterator(); - while (fIter.hasElement()) - { - def = fIter.nextElement(); - if (strcmp(def->fldName_, fkFldName) == 0) - { - if(NULL == def->bindVal_ && isInsert) { return true; } - if(NULL == def->bindVal_) { - if (def->type_ != typeVarchar) - val = (char*)curTuple_+ def->offset_; - else val = (void *) *(long *) ((char*)curTuple_+ - def->offset_); - } else { - val = def->bindVal_; - } - if(def->type_==typeString) - condition[i].setTerm(pkFldName,OpEquals,&val); - else - condition[i].setTerm(pkFldName,OpEquals,val); - i++; - break; - } - } - } - pkFieldList.removeAll(); - fkFieldList.removeAll(); - Condition *cond = NULL; - if(i == 0 && !isInsert)return true; - if( i > 1){ - cond = new Condition[i-1]; - int totcon = i; - i=0; - int j=0; - for(j=0;jsetCondition(&cond[j-1]); - } - else{ - fkTbl->setCondition(&condition[i-1]); - } - fkTbl->execute(); - if(fkTbl->fetch()){ - fkTbl->closeScan(); - delete[] cond; - delete[] condition; - return true; - } - delete[] cond; - delete[] condition; - return false; -} - -bool TableImpl::isFkTableHasRecord(char *pkTableName, TableImpl *fkTbl) -{ - DbRetVal rv=OK; - FieldNameList pkFieldList,fkFieldList; - void *tPkptr =NULL; - void *tFkptr = NULL; - void *chunkPk = NULL; - void *vcchunkPk = NULL; - CatalogTableTABLE cTable(sysDB_); - rv = cTable.getChunkAndTblPtr(getName(), chunkPk, tPkptr, vcchunkPk); - if ( OK != rv){return false;} - rv = cTable.getChunkAndTblPtr(pkTableName, chunkPk, tFkptr, vcchunkPk); - if ( OK != rv){return false;} - CatalogTableFK cFk(sysDB_); - rv = cFk.getPkFkFieldInfo(tPkptr,tFkptr,pkFieldList,fkFieldList); - if ( OK != rv){return false;} - int totFld = pkFieldList.size(); - Condition *condition = new Condition[totFld]; - char *pkFldName = NULL; - char *fkFldName = NULL; - FieldDef *def=NULL; - int i=0; - pkFieldList.resetIter(); - fkFieldList.resetIter(); - while((pkFldName = pkFieldList.nextFieldName())!= NULL) - { - fkFldName = fkFieldList.nextFieldName(); - FieldIterator fIter = fldList_.getIterator(); - while (fIter.hasElement()) - { - def = fIter.nextElement(); - void *val = NULL; - if (def->type_ != typeVarchar) - val = (char*)curTuple_+ def->offset_; - else val = (void *) *(long *) ((char*)curTuple_+ def->offset_); - if (strcmp(def->fldName_, pkFldName) == 0) - { - if(def->type_==typeString) - condition[i].setTerm(fkFldName,OpEquals,&val);//((char*)curTuple_+def->offset_)); - else - condition[i].setTerm(fkFldName,OpEquals,val);//((char*)curTuple_+def->offset_)); - i++; - break; - } - } - } - pkFieldList.removeAll(); - fkFieldList.removeAll(); - if(i == 0 )return true; - Condition *cond = new Condition[i-1]; - i=0; - int j=0; - for(j=0;jsetCondition(&condition[totFld-1]); - else - fkTbl->setCondition(&cond[j-1]); - fkTbl->execute(); - if(fkTbl->fetch()){ - fkTbl->closeScan(); - delete[] cond; - delete[] condition; - return true; - } - delete[] cond; - delete[] condition; - return false; -} diff --git a/src/storage/TableImplReadOp.cxx b/src/storage/TableImplReadOp.cxx deleted file mode 100644 index 7060d423..00000000 --- a/src/storage/TableImplReadOp.cxx +++ /dev/null @@ -1,578 +0,0 @@ -/*************************************************************************** - * 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 //for AggType - -DbRetVal TableImpl::optimize() -{ - //table ptr is set in predicate because it needs to access the - //type and length to evaluate - if( NULL != pred_) - { - PredicateImpl *pred = (PredicateImpl*) pred_; - pred->setTable(this); - pred->setProjectionList(NULL); - pred->setOffsetAndType(); - } - DbRetVal rv = createPlan(); - if (rv != OK) return rv; - if (iter) { iter->close(); delete iter; iter = NULL; } - if (useIndex_ >= 0) - iter = new TupleIterator(pred_, scanType_, idxInfo[useIndex_], chunkPtr_, sysDB_->procSlot,isBetween,isPointLook,shouldNullSearch); - else if (scanType_ == fullTableScan) - iter = new TupleIterator(pred_, scanType_, NULL, chunkPtr_, sysDB_->procSlot,isBetween,isPointLook,shouldNullSearch); - else - { - printError(ErrSysFatal,"Unable to create tuple iterator"); - //should never happen - return ErrSysFatal; - } - iter->setPlan(); - return OK; -} - -DbRetVal TableImpl::execute() -{ - if (iter && !iter->isIterClosed()) - { - //printError(ErrAlready,"Scan already open:Close and re execute"); - return ErrAlready; - } - DbRetVal ret = OK; - if (!isPlanCreated) ret = optimize(); - if (OK != ret) - { - printError(ErrSysInternal,"Unable to create the plan"); - return ErrSysInternal; - } - ret = iter->open(); - if (OK != ret) - { - printError(ret,"Unable to open the iterator"); - return ret; - } - return OK; -} - - -DbRetVal TableImpl::createPlan() -{ - if (isPlanCreated) { - //will do early return here. plan is generated only when setPredicate is called. - if (scanType_ == unknownScan) return ErrSysFatal; //this should never happen - else return OK; - } - isBetween=false; - isPointLook = false; - useIndex_ = -1; - - FieldIterator fIter = fldList_.getIterator(); - FieldDef *def = NULL; - while ((def = fIter.nextElement())!= NULL) { - if (NULL != def->bindVal_) bindList_.append(def); - } - numBindFlds_ = bindList_.size(); - if (bindListArray_) { ::free(bindListArray_); bindListArray_ = NULL; } - bindListArray_ = (void **) malloc(numBindFlds_ * sizeof (void *)); - void *elem = NULL; - int i = 0; - ListIterator it = bindList_.getIterator(); - while ((elem = it.nextElement()) != NULL) bindListArray_[i++] = elem; - scanType_ = fullTableScan; - isPlanCreated = true; - - //if there are no predicates then go for full scan - //if there are no indexes then go for full scan - if (NULL == pred_ || NULL == indexPtr_) - { - return OK; - } - if (NULL != indexPtr_) - { - PredicateImpl *pred = (PredicateImpl*)pred_; - //If searching for IS NULL or IS NOT NULL then fullscan - if(pred->isIsNullInvolved()) - { - scanType_ = fullTableScan; - shouldNullSearch=true; - return OK; - } - printDebug(DM_Predicate, "predicate does not involve NOT , OR operator"); - if (!pred->isNotOrInvolved()) - { - printDebug(DM_Predicate, "predicate does not involve NOT , OR operator"); - for (int i =0; i < numIndexes_; i++) - { - bool isAllFldPointLookup = true; - HashIndexInfo* info = (HashIndexInfo*) idxInfo[i]; - FieldIterator iter = info->idxFldList.getIterator(); - int noOfIfld =0; - while(iter.hasElement()) - { - noOfIfld++; - FieldDef *def = iter.nextElement(); - if (pred->pointLookupInvolved(def->fldName_)) - { - if (!isAllFldPointLookup) break; - printDebug(DM_Predicate, "point lookup involved for field %s",def->fldName_); - if(hashIndex == info->indType) - scanType_ = hashIndexScan; - else if (trieIndex == info->indType) - scanType_ = trieIndexScan; - else - scanType_ = treeIndexScan; - isPointLook = true; - useIndex_ = i; - } - else if (pred->isBetweenInvolved(def->fldName_)) - { - if (treeIndex == info->indType) - { - scanType_ = treeIndexScan; - useIndex_ = i; - isBetween=true; - break; //no composite index for tree index - } else isAllFldPointLookup= false; - } - else if (pred->rangeQueryInvolved(def->fldName_)) - { - printDebug(DM_Predicate, "range lookup involved for field %s",def->fldName_); - if (treeIndex == info->indType) - { - scanType_ = treeIndexScan; - useIndex_ = i; - break; //no composite index for tree index - } else isAllFldPointLookup=false; - }else { - useIndex_ = -1; - isAllFldPointLookup = false; - break; - } - }//while iter.hasElement() - if( noOfIfld == 1 && useIndex_ != -1)return OK; - if (!isAllFldPointLookup && useIndex_ != -1) return OK; - }//for - } - } - scanType_ = fullTableScan; - return OK; -} - -void* TableImpl::fetch() -{ - fetchNoBind(); - if (NULL == curTuple_) return curTuple_; - copyValuesToBindBuffer(curTuple_); - return curTuple_; -} - -void* TableImpl::fetch(DbRetVal &rv) -{ - fetchNoBind(rv); - if (NULL == curTuple_) return curTuple_; - copyValuesToBindBuffer(curTuple_); - return curTuple_; -} - -void* TableImpl::fetchNoBind() -{ - if (NULL == iter) - { - printError(ErrNotOpen,"Scan not open or Scan is closed\n"); - return NULL; - } - void *prevTuple = curTuple_; - curTuple_ = iter->next(); - if (NULL == curTuple_) - { - return NULL; - } - DbRetVal lockRet = OK; - if (!loadFlag) { - if ((*trans)->isoLevel_ == READ_COMMITTED) - { - //if iso level is read committed, operation duration lock is sufficent - //so release it here itself. - int tries = Conf::config.getMutexRetries(); - struct timeval timeout, timeval; - timeout.tv_sec = Conf::config.getMutexSecs(); - timeout.tv_usec = Conf::config.getMutexUSecs(); - - bool status = false; - while(true) { - lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status); - if (OK != lockRet) - { - printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); - curTuple_ = prevTuple; - return NULL; - } - if (!status) break; - tries--; - if (tries == 0) break; - timeval.tv_sec = timeout.tv_sec; - timeval.tv_usec = timeout.tv_usec; - os::select(0, 0, 0, 0, &timeval); - } - if (tries == 0) - { - printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); - curTuple_ = prevTuple; - return NULL; - } - } - else if ((*trans)->isoLevel_ == READ_REPEATABLE) { - if (OK != trySharedLock(curTuple_, trans)) - { - printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); - curTuple_ = prevTuple; - return NULL; - } - - } - } - return curTuple_; -} - -void* TableImpl::fetchNoBind(DbRetVal &rv) -{ - rv = OK; - if (NULL == iter) - { - printError(ErrNotOpen,"Scan not open or Scan is closed\n"); - rv = ErrNotOpen; - return NULL; - } - void *prevTuple = curTuple_; - curTuple_ = iter->next(); - if (NULL == curTuple_) - { - return NULL; - } - DbRetVal lockRet = OK; - if (!loadFlag) { - if ((*trans)->isoLevel_ == READ_REPEATABLE) { - lockRet = lMgr_->getSharedLock(curTuple_, trans); - if (OK != lockRet) - { - printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); - rv = ErrLockTimeOut; - curTuple_ = prevTuple; - return NULL; - } - - } - else if ((*trans)->isoLevel_ == READ_COMMITTED) - { - //if iso level is read committed, operation duration lock is sufficent - //so release it here itself. - int tries = Conf::config.getMutexRetries(); - //struct timeval timeout; - //timeout.tv_sec = Conf::config.getMutexSecs(); - //timeout.tv_usec = Conf::config.getMutexUSecs(); - - bool status = false; - while(true) { - lockRet = lMgr_->isExclusiveLocked( curTuple_, trans, status); - if (OK != lockRet) - { - printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); - curTuple_ = prevTuple; - rv = ErrLockTimeOut; - return NULL; - } - if (!status) break; - tries--; - if (tries == 0) break; - //os::select(0, 0, 0, 0, &timeout); - } - if (tries == 0) - { - printError(lockRet, "Unable to get the lock for the tuple %x", curTuple_); - curTuple_ = prevTuple; - rv = ErrLockTimeOut; - return NULL; - } - } - } - return curTuple_; -} - -DbRetVal TableImpl::fetchAgg(const char * fldName, AggType aType, void *buf, bool &noRec) -{ - FieldInfo *info = new FieldInfo(); - DbRetVal rv = getFieldInfo(fldName, info); - if (OK != rv) return rv; - bool res= false; - if (AGG_MIN == aType || AGG_MAX == aType) { - int pos =0; - IndexType iType = getIndexType((char*)fldName, &pos); - if(treeIndex == iType && pos >=0) { - if (AGG_MIN == aType) { - HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos]; - CINDEX *iptr = (CINDEX*) hInfo->indexPtr; - TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_; - TreeIter *iter=NULL; - if(fstNode!=NULL){ - TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode))); - iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot); - }else{ - iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot); - } - char *tuple = (char*) iter->getFirstElement(); - if (tuple != NULL) { - AllDataType::copyVal(buf,(void*)(tuple+info->offset), - info->type, info->length); - delete iter; - return OK; - } - delete iter; iter = NULL; - } - else if (AGG_MAX == aType) { - HashIndexInfo* hInfo = (HashIndexInfo*) idxInfo[pos]; - CINDEX *iptr = (CINDEX*) hInfo->indexPtr; - TreeNode *fstNode=(TreeNode *)iptr->hashNodeChunk_; - TreeIter *iter=NULL; - if(fstNode!=NULL){ - TreeNode *start = (TreeNode *)*((char**)((char*)fstNode + sizeof(TreeNode))); - iter = new TreeIter(start,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot); - }else{ - iter = new TreeIter(NULL,(TreeNode*)iptr->hashNodeChunk_,sysDB_->procSlot); - } - char *tuple = (char*) iter->getLastElement(); - if (tuple != NULL) { - AllDataType::copyVal(buf,(void*)(tuple+info->offset), - info->type, info->length); - delete iter; iter = NULL; - return OK; - } - delete iter; iter=NULL; - } - } - }else if (AGG_COUNT == aType) { - (*(int*)buf) = 0; - } - - - DataType type = info->type; - int length = info->length; - int offset = info->offset; - int colPos = fldList_.getFieldPosition(fldName); - bool isNullable= true; - if (info->isNull || info->isPrimary || info->isDefault || info->isAutoIncrement) { - isNullable = false; - } - int nullOffset = length_-4; - if (aType == AGG_COUNT) { - length = sizeof(int); - type = typeInt; - } - if (NULL == pred_ && typeInt == type && aType != AGG_AVG) - { //perf opt - ChunkIterator cIter = ((Chunk*)chunkPtr_)->getIterator(); - char *tuple =(char*)cIter.nextElement(); - if (NULL == tuple) { - *(int *) buf = 0; - noRec = true; - return OK; - } - int count =1; - if (isNullable) { - if (isIntUsedForNULL) { - if (BITSET(*(int*)(tuple+nullOffset), colPos-1)) count =0; - } - else { - curTuple_= tuple; - if(isFldNull(colPos)) count =0; - } - } - if (aType != AGG_COUNT) - AllDataType::copyVal(buf, (void*) (tuple+offset), type, length); - void *prev=NULL; - prev = curTuple_; - cIter.pageSize = PAGE_SIZE; - while(1) - { - tuple = (char*)cIter.nextElementInt(); - if (NULL == tuple) break; - if (isNullable) { - if (isIntUsedForNULL) { - if (BITSET(*(int*)(tuple+nullOffset), colPos-1)) continue; - } - else { - curTuple_= tuple; - if(isFldNull(colPos)) continue; - } - } - if (aType == AGG_MIN) - { - if (*(int*)buf >= *((int*)(tuple+offset))) - *(int*)buf = *((int*)(tuple+offset)); - } - else if (aType == AGG_MAX) - { - if (*(int*)buf <= *((int*)(tuple+offset))) - *(int*)buf = *((int*)(tuple+offset)); - } - else if (aType == AGG_SUM) - { - *(int*)buf += *((int*)(tuple+offset)); - } - else if (aType == AGG_AVG) - { - *(int*)buf = *(int*)buf + *((int*)(tuple+offset)); - count++; - } - else if (aType == AGG_COUNT) - { - count++; - } - } - curTuple_= prev; - if( AGG_AVG == aType) AllDataType::divVal(buf, &count, type); - else if (AGG_COUNT == aType) (*(int*)buf) = count; - delete info; - return OK; - } - - char *tuple = (char*) fetchNoBind(rv); - if ( NULL == tuple) { noRec = true; return OK; } - int count =1; - - while(isFldNull(colPos)) { - tuple= (char*) fetchNoBind(rv); - if (aType == AGG_COUNT) count++; - if (tuple) break; - } - if ( NULL == tuple) { noRec = true; return OK; } - - if (aType == AGG_AVG) { - AllDataType::convertToDouble(buf, (void*) (tuple+offset), type); - } else if (aType != AGG_COUNT) { - AllDataType::copyVal(buf, (void*) (tuple+offset), type, length); - } - while(1) { - tuple = (char*) fetchNoBind(rv); - if (NULL == tuple) break; - if (isNullable) { - if (isIntUsedForNULL) { - if (BITSET(*(int*)(tuple+nullOffset), colPos-1)) continue; - } - else { - curTuple_= tuple; - if(isFldNull(colPos)) continue; - } - } - switch(aType) { - case AGG_MIN: - { - res = AllDataType::compareVal(buf, (void*) (tuple+offset), - OpGreaterThanEquals, - type, length); - if (res) AllDataType::copyVal(buf, (void*) (tuple+offset), - type, length); - break; - } - case AGG_MAX: - { - res = AllDataType::compareVal(buf, (void*) (tuple+offset), - OpLessThanEquals, - type, length); - if (res) AllDataType::copyVal(buf, (void*) (tuple+offset), - type, length); - break; - } - case AGG_SUM: - { - AllDataType::addVal(buf, (void*) (tuple+offset), - type); - break; - } - case AGG_AVG: - { - double tmpBuf=0.0; - AllDataType::convertToDouble(&tmpBuf, (void*) (tuple+offset), type); - AllDataType::addVal(buf, &tmpBuf, typeDouble); - count++; - break; - } - case AGG_COUNT: - { - count++; - break; - } - } - } - switch(aType) { - case AGG_AVG: - { - AllDataType::divVal((double *)buf, count, type); - break; - } - case AGG_COUNT: - { - (*(int*)buf) = count; - break; - } - } - delete info; - return OK; -} - -long TableImpl::numTuples() -{ - return ((Chunk*)chunkPtr_)->getTotalDataNodes(); -} - -DbRetVal TableImpl::closeScan() -{ - //do not throw scan not open error - //this function will be called by table handle - if (iter) { - iter->close(); - } - return OK; -} - -bool TableImpl::pushPredicate(Predicate *pred) -{ - bool ret = false; - PredicateImpl *pImpl = (PredicateImpl*) pred; - char tableName[IDENTIFIER_LENGTH]; - Table::getTableNameAlone(pImpl->getFldName1(), tableName); - //printf("predicate tbl name %s\n", tableName); - - //if predicate is of form t1.f1=t2.f1 then do not push here - bool isAliasSet = (0 !=strcmp(getAliasName(),"")) ; - if (0 != strcmp(pImpl->getFldName2(),"")) return ret; - - if (0 == strcmp(getName(), tableName) ||(isAliasSet && 0 == strcmp(getAliasName(), tableName))) - { - setPredicate(pred); - //printf("PRABA::pushed predicate in tablehdl %s\n", getName()); - ret = true; - } - return ret; -} diff --git a/src/storage/TreeIndex.cxx b/src/storage/TreeIndex.cxx deleted file mode 100644 index 97e12cd8..00000000 --- a/src/storage/TreeIndex.cxx +++ /dev/null @@ -1,496 +0,0 @@ -/*************************************************************************** - * 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 -DbRetVal TreeIndex::deleteLogicalUndoLog(Database *sysdb, void *data) -{ - DbRetVal rv = OK; - TreeUndoLogInfo *tUndoInfo = (TreeUndoLogInfo *) data; - Database *db = new Database(); - db->setMetaDataPtr((DatabaseMetaData*) tUndoInfo->metaData_); - db->setProcSlot(sysdb->procSlot); - CINDEX *iptr = (CINDEX*) tUndoInfo->cIndex_; - TreeNode *start = (TreeNode*) iptr->hashNodeChunk_; - //HashIndexInfo populated here - HashIndexInfo *info = new HashIndexInfo(); - info->indexPtr = (char *)iptr; - info->noOfBuckets = iptr->noOfBuckets_; - info->isUnique = iptr->isUnique_; - info->type = ((CFIELD*)(((CINDEXFIELD*)(iptr->fstIndFld_))->fieldPtr))->type_; - info->fldOffset = ((CFIELD*)(((CINDEXFIELD*)(iptr->fstIndFld_))->fieldPtr))->offset_; - info->indType = iptr->indexType_; - TreeIndex *treeInd = (TreeIndex*)Index::getIndex(iptr->indexType_); - int pos=0; - TreeNode *fltnode = start->locateNode(db, start, tUndoInfo->tuple_, info,rv); - if (NULL == fltnode){ - delete db; - delete info; - return rv; - } //First Level Node Not found - TreeNode *iter = start->locateNodeFromFirstLevel(fltnode, info, tUndoInfo->tuple_, &pos); - if (NULL == iter){ - fltnode->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - delete db; - delete info; - return OK; - } //element not found - rv = treeInd->removeElement(db, iter, tUndoInfo->tuple_, info); - if( rv != OK ){ - fltnode->mutex_.releaseShareLock(db->procSlot); - printError(rv, "Romove from TreeNode Failed "); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - delete db; - delete info; - return rv; - } - if(0 == iter->noElements_) - { - treeInd->removeNode(db, tUndoInfo->cIndex_, fltnode,iter, pos); - }else { fltnode->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - } - delete db; - delete info; - return rv; -} - -DbRetVal TreeIndex::insertLogicalUndoLog(Database *sysdb, void *data) -{ - DbRetVal rc = OK; - TreeUndoLogInfo *tUndoInfo = (TreeUndoLogInfo *) data; - Database *db = new Database(); - db->setMetaDataPtr((DatabaseMetaData*) tUndoInfo->metaData_); - db->setProcSlot(sysdb->procSlot); - CINDEX *iptr = (CINDEX*) tUndoInfo->cIndex_;//CINDEX - //HashIndexInfo populated here - HashIndexInfo *info = new HashIndexInfo(); - info->indexPtr = (char *)iptr; - info->noOfBuckets = iptr->noOfBuckets_; - info->isUnique = iptr->isUnique_; - info->type = ((CFIELD*)(((CINDEXFIELD*)(iptr->fstIndFld_))->fieldPtr))->type_; - info->fldOffset = ((CFIELD*)(((CINDEXFIELD*)(iptr->fstIndFld_))->fieldPtr))->offset_; - info->indType = iptr->indexType_; - TreeNode *start = (TreeNode*) iptr->hashNodeChunk_; - int offset = info->fldOffset; - DataType type = info->type; - void *keyPtr =(void*)((char*)tUndoInfo->tuple_ + offset); - if (start == NULL) - { - //Currently Nodes are not deleted - printDebug(DM_TreeIndex, "Inside if - start=NULL create First level "); - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - TreeNode *tnode = (TreeNode*) chunk->allocate(db, &rc); - if (tnode == NULL) - { - printError(rc, "Exit TreeNode::Insert - 1 tnode=NULL"); - delete info; - return rc; - } - tnode->mutex_.init("TNODE-R"); - tnode->min_ = tUndoInfo->tuple_; - tnode->max_ = tUndoInfo->tuple_; - tnode->noElements_ =1; - tnode->next_ = NULL; - tnode->prev_ = NULL; - tnode->balance_ = 0; - char **rec = (char**)((char*) tnode + sizeof(TreeNode)); - //printDebug(DM_TreeIndex, "\nStoring first record at %x\n", rec); - *rec = (char*) tUndoInfo->tuple_; - - printDebug(DM_TreeIndex, "Inside if - start=NULL create second level "); - Chunk *ftchunk = (Chunk*) iptr->chunkPtr_; - TreeNode *ftnode = (TreeNode*) ftchunk->allocate(db, &rc); - if (NULL == ftnode) - { - printError(rc, "Unable to allocate tree node"); - chunk->free(db, tnode); - delete info; - return rc; - } - ftnode->mutex_.init("TNODE-I"); - ftnode->min_= NULL; - ftnode->max_ = NULL; - ftnode->noElements_ =1; - ftnode->next_ = NULL; - ftnode->prev_ = NULL; - ftnode->balance_ = 0; - char **tn=(char**)((char*) ftnode+sizeof(TreeNode)); - *tn = (char*)tnode; - //iptr->hashNodeChunk_ = ftnode; - if( 0 !=Mutex::CASL((long*)&iptr->hashNodeChunk_, 0, (long)ftnode)) - { - printError(ErrLockTimeOut, "Lock timeout..retry"); - chunk->free(db, tnode); - chunk->free(db, ftnode); - delete info; - return ErrLockTimeOut; - } - }else { - rc = start->insert(db, info, iptr, tUndoInfo->tuple_); - if (rc != OK){ - delete db; delete info; - printError(rc, "Error in tree node insertion\n"); - return rc; - } - } - delete db; - delete info; - return rc; - -} - -DbRetVal TreeIndex::insert(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool undoFlag) -{ - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - TreeNode *start = (TreeNode*) iptr->hashNodeChunk_; - DbRetVal rc = OK; - int offset = info->fldOffset; - DataType type = info->type; - void *keyPtr =(void*)((char*)tuple + offset); - //TreeUndoLogInfo Populated here - TreeUndoLogInfo hInfo; - hInfo.metaData_ = tbl->db_->getMetaDataPtr(); - hInfo.tuple_ = tuple; - hInfo.cIndex_= indexPtr; - if (start == NULL) - { - printDebug(DM_TreeIndex, "Inside if - start=NULL create First level "); - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - TreeNode *tnode = (TreeNode*) chunk->allocate(tbl->db_, &rc); - if (tnode == NULL) - { - printError(rc, "Unable to allocate tree node"); - return rc; - } - tnode->mutex_.init("TNODE-R"); - tnode->min_ = tuple; - tnode->max_ = tuple; - tnode->noElements_ =1; - tnode->next_ = NULL; - tnode->prev_ = NULL; - tnode->balance_ = 0; - char **rec = (char**)((char*) tnode + sizeof(TreeNode)); - //printDebug(DM_TreeIndex, "\nStoring first record at %x\n", rec); - *rec = (char*) tuple; - - printDebug(DM_TreeIndex, "Inside if - start=NULL create second level "); - TreeNode *ftnode = (TreeNode*) chunk->allocate(tbl->db_, &rc); - if (NULL == ftnode) - { - printError(rc, "Unable to allocate tree node"); - chunk->free(tbl->db_, tnode); - return rc; - } - ftnode->mutex_.init("TNODE-I"); - ftnode->min_= NULL; - ftnode->max_ = NULL; - ftnode->noElements_ =1; - ftnode->next_ = NULL; - ftnode->prev_ = NULL; - ftnode->balance_ = 0; - //TODO: Handle when two process try to allocate first node - char **tn=(char**)((char*) ftnode + sizeof(TreeNode)); - *tn = (char*)tnode; - if( 0 !=Mutex::CASL((long*)&iptr->hashNodeChunk_, 0, (long)ftnode)) - { - printError(ErrLockTimeOut, "Lock timeout..retry"); - chunk->free(tbl->db_, tnode); - chunk->free(tbl->db_, ftnode); - return ErrLockTimeOut; - } - - }else { - rc = start->insert(tbl->db_, indInfo, indexPtr, tuple); - if (rc != OK){ - printError(rc, "Error in tree node insertion for tuple %x", tuple); - return rc; - } - } - //start->displayAll(offset); - if(!undoFlag){ - rc = tr->appendLogicalTreeUndoLog(tbl->sysDB_, InsertTreeIndexOperation, &hInfo, sizeof(TreeUndoLogInfo)); - if (rc !=OK) - { - //Reverse back - int pos=0; - start = (TreeNode*) iptr->hashNodeChunk_; - TreeNode *fltnode = start->locateNode(tbl->sysDB_,start, tuple, indInfo,rc); - if (NULL == fltnode) - { - return rc; - } //First Level Node Not found - TreeNode *iter = start->locateNodeFromFirstLevel(fltnode, indInfo, tuple, &pos); - if (NULL == iter){ - fltnode->mutex_.releaseShareLock(tbl->sysDB_->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - return OK; - } //element not found - rc = removeElement(tbl->getDB(), iter, tuple, info); - if( rc != OK ) - { - fltnode->mutex_.releaseShareLock(tbl->sysDB_->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - printError(rc, "Romove from TreeNode Failed "); - return rc; - } - if(0 == iter->noElements_) - { - removeNode(tbl->getDB(), indexPtr, fltnode,iter, pos); - }else - { - fltnode->mutex_.releaseShareLock(tbl->sysDB_->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - } - - printError(ErrSysFatal, "Unable to append undo lock for TreeInsert\n"); - return rc; - - } - } - return rc; -} - - -DbRetVal TreeIndex::remove(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool undoFlag) -{ - DbRetVal rc = OK; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - TreeNode *start = (TreeNode*) iptr->hashNodeChunk_; - int pos=0; - TreeNode *fltnode = start->locateNode(tbl->getDB(),start, tuple, indInfo,rc); - if (NULL == fltnode) return rc; //First Level Node Not found - TreeNode *iter = start->locateNodeFromFirstLevel(fltnode, indInfo, tuple, &pos); - if (NULL == iter) { - //element not found - fltnode->mutex_.releaseShareLock((tbl->getDB())->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - return OK; - } - rc = removeElement(tbl->getDB(), iter, tuple, info); - if( rc != OK ){ - fltnode->mutex_.releaseShareLock((tbl->getDB())->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - printError(rc, "Remove from TreeNode Failed"); - return rc; - } - if(0 == iter->noElements_) - { - removeNode(tbl->getDB(), indexPtr, fltnode, iter, pos); - }else - { - fltnode->mutex_.releaseShareLock((tbl->getDB())->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - } - TreeUndoLogInfo hInfo; - hInfo.metaData_ = tbl->db_->getMetaDataPtr(); - hInfo.tuple_ = tuple; - hInfo.cIndex_= indexPtr; - if (!undoFlag) { - rc =tr->appendLogicalTreeUndoLog(tbl->sysDB_, DeleteTreeIndexOperation, &hInfo, sizeof(TreeUndoLogInfo)); - if( rc != OK){ - //Reverse back - //Currently nodes are not freed - rc = start->insert(tbl->db_, info, iptr, tuple); - if (rc != OK){ printError(ErrSysFatal, "double failure on undo log remove followed by tree insert\n");} - printError(ErrSysFatal, "Unable to append undo lock for TreeRemove\n"); - return rc; - } - } - return rc; -} - -void TreeIndex::removeNode(Database *db,void *indexPtr,TreeNode *fltnode, TreeNode *node,int pos) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - char **nod = (char**)((char*)fltnode + sizeof(TreeNode)); - char *tmp = (char *)malloc(sizeof(void *) * (fltnode->noElements_ - pos)); - memcpy(tmp, (char*)nod + ((pos+1) * sizeof(void *)), sizeof(void *) * (fltnode->noElements_ - pos)); - memcpy((char*)nod + ((pos) * sizeof(void *)), tmp, sizeof(void *) * (fltnode->noElements_ - pos)); - free(tmp); - fltnode->noElements_--; - if(node->prev_!=NULL) node->prev_->next_= node->next_; - if(node->next_!=NULL) node->next_->prev_= node->prev_; - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - chunk->free(db, node); - printDebug(DM_TreeIndex,"TreeNode at postion %d Freed",pos); - if(fltnode->noElements_== 0) - { - if(fltnode->prev_!=NULL) { - fltnode->prev_->next_= fltnode->next_; - } - else { - iptr->hashNodeChunk_ = fltnode->next_ ; - } - if(fltnode->next_!=NULL) { - fltnode->next_->prev_= fltnode->prev_; - } - //need discussion in the above situation to solve concureny - printDebug(DM_TreeIndex,"TreeNode from first level Freed"); - fltnode->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - chunk->free(db, fltnode); - }else{ - fltnode->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fltnode); - } -} - -DbRetVal TreeIndex::removeElement(Database *db, TreeNode *iter, void *tuple, HashIndexInfo *info) -{ - void *searchKey =(void*)((char*)tuple + info->fldOffset); - int loc=0, middle=0, start=0, end=iter->noElements_-1; - char **rec = (char**)((char*)iter + sizeof(TreeNode)); - DbRetVal ret = TreeIndex::upgradeTreeNodeMutex(iter, db->procSlot); - if (OK != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - return ErrLockTimeOut; - } - for(middle = (start + end) / 2; start <= end ; middle = (start +end )/2) - { - loc = middle; - char *record = ((char*)*(rec+middle)) + info->fldOffset; - bool res = AllDataType::compareVal(searchKey, record, OpLessThan, - info->type, info->compLength); - if(res) - { - end = middle - 1; - } - else - { - res = AllDataType::compareVal(searchKey, record, OpGreaterThan, - info->type, info->compLength); - if (res) { - start = middle + 1; - loc = start; - } else { - loc = middle; - break; - } - } - } - if (loc == iter->noElements_-1) - { - iter->max_ = *(char**)((char*)rec + ((loc-1) * sizeof(void *))); - }else { - char *tmp = (char *)malloc(sizeof(void *) * (iter->noElements_ - loc)); - memcpy(tmp, (char*)rec + ((loc+1) * sizeof(void *)), - sizeof(void *) * (iter->noElements_ - loc)); - memcpy((char*)rec + ((loc) * sizeof(void *)), tmp, - sizeof(void *) * (iter->noElements_ - loc)); - free(tmp); - } - if(loc==0) - { - iter->min_ = *(char**)rec ; - } - iter->noElements_--; - iter->mutex_.releaseShareLock(db->procSlot); - return OK; -} - - -DbRetVal TreeIndex::update(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool undoFlag) -{ - CINDEX *iptr = (CINDEX*)indexPtr; - - HashIndexInfo *info = (HashIndexInfo*) indInfo; - //check whether the index key is updated or not - //if it is not updated return from here - bool keyNotUpdated = false; - FieldIterator idxFldIter = info->idxFldList.getIterator(); - while (idxFldIter.hasElement()) - { - FieldDef *idef = idxFldIter.nextElement(); - FieldIterator fldIter = tbl->fldList_.getIterator(); - while (fldIter.hasElement()) - { - FieldDef *def = fldIter.nextElement(); - if (0 == strcmp(def->fldName_, idef->fldName_)) - { - if (NULL != def->bindVal_) - { - //Not Implemented - return ErrNotYet; - } - keyNotUpdated = true; - break; - } - } - } - if (keyNotUpdated) - { - return OK; - } - return ErrNotYet; -} - -DbRetVal TreeIndex::getTreeNodeMutex(TreeNode *node, int procSlot, bool isX) -{ - struct timeval timeout, timeval; - timeout.tv_sec = Conf::config.getMutexSecs(); - timeout.tv_usec = Conf::config.getMutexUSecs(); - int tries=0; - int totalTries = Conf::config.getMutexRetries() *2; - int ret =0; - while (tries < totalTries) - { - ret = 0; - if (isX) - ret = node->mutex_.getExclusiveLock(procSlot,true); - else - ret = node->mutex_.getShareLock(procSlot,true); - if (ret == 0) break; - timeval.tv_sec = timeout.tv_sec; - timeval.tv_usec = timeout.tv_usec; - os::select(0, 0, 0, 0, &timeval); - tries++; - } - if (tries >= totalTries) return ErrLockTimeOut; - return OK; - -} - -DbRetVal TreeIndex::upgradeTreeNodeMutex(TreeNode *node, int procSlot) -{ - struct timeval timeout, timeval; - timeout.tv_sec = Conf::config.getMutexSecs(); - timeout.tv_usec = Conf::config.getMutexUSecs(); - int tries=0; - int totalTries = Conf::config.getMutexRetries() *2; - int ret =0; - while (tries < totalTries) - { - ret = 0; - ret = node->mutex_.getExclusiveLock(procSlot,true, true); - if (ret == 0) break; - timeval.tv_sec = timeout.tv_sec; - timeval.tv_usec = timeout.tv_usec; - os::select(0, 0, 0, 0, &timeval); - tries++; - } - if (tries >= totalTries) return ErrLockTimeOut; - return OK; -} - diff --git a/src/storage/TreeIter.cxx b/src/storage/TreeIter.cxx deleted file mode 100644 index aea8be10..00000000 --- a/src/storage/TreeIter.cxx +++ /dev/null @@ -1,333 +0,0 @@ -/*************************************************************************** - * 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 - -void* TreeIter::getFirstElement() -{ - if (NULL == iter) return NULL; - TreeNode *node = iter; - while(node != NULL) { - if(NULL == node->prev_) break; - node = node->prev_; - } - if (node == NULL) printf("Node returned is NULL\n"); - if (0 == node->noElements_) return NULL; - char **rec = (char**)((char*)node + sizeof(TreeNode)); - int loc = 0; //first element - char **tuple = (char**)((char*)rec + (loc * sizeof(void *))); - return *tuple; -} - -void* TreeIter::getLastElement() -{ - if (NULL == iter) return NULL; - TreeNode *node = iter; - while(node != NULL ) { - if(NULL == node->next_) break; - node = node->next_; - } - if (node == NULL) printf("Node returned is NULL\n"); - if (0 == node->noElements_) return NULL; - char **rec = (char**)((char*)node + sizeof(TreeNode)); - int loc = node->noElements_-1; //last element - char **tuple = (char**)((char*)rec + (loc * sizeof(void *))); - return *tuple; -} - -void* TreeIter::prev() -{ - if (0 != nodeOffset ) - { - nodeOffset--; - - }else - { - iter=iter->prev_; - if (NULL == iter) return NULL; - nodeOffset = iter->noElements_; - } - char **rec = (char**)((char*)iter + sizeof(TreeNode)); - rec = (char**)((char *)rec + ((nodeOffset) * sizeof(void **))); - return *rec; -} - -void TreeIter::nextNode() -{ - if (recordsOver) return ; - if (NULL == iter) return ; - TreeNode *tmpIter = iter; - iter = iter->next_; - if(iter){ - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter, procSlot); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - tmpIter->mutex_.releaseShareLock(procSlot); - return ; - } - } - tmpIter->mutex_.releaseShareLock(procSlot); - nodeOffset=0; -} - -void TreeIter::reset() -{ - if(iter && !firstCall) iter->mutex_.releaseShareLock(procSlot); - firstCall = true; - recordsOver=false; - iter = head; -} - -void* TreeIter::next() -{ - int direction=0; - if (recordsOver){ - if(iter) iter->mutex_.releaseShareLock(procSlot); - iter = NULL; - return NULL; - } - if (NULL== iter) return NULL; - if (firstCall) - { - if (OpLessThan ==op || OpLessThanEquals == op) - { - nodeOffset = 1; - firstCall = false; - char **rec = (char**)((char*) iter + sizeof(TreeNode)); - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter, procSlot); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - return NULL; - } - //iter->displayAll(fldOffset); - return *rec; - } - else if (OpGreaterThan == op) - { - char *rec = (char*)locateNode(); - firstCall = false; - if(rec){ - bool result = AllDataType::compareVal(searchKey, rec+fldOffset, - OpEquals, type, length); - //equals comparision does not apply to float and double - if (result || type==typeFloat || type == typeDouble) return next(); - } - return rec; - }else if (OpGreaterThanEquals == op) - { - void *rec = locateNode(); - firstCall = false; - return rec; - }else if (OpEquals == op) - { - void *rec = locateNode(); - firstCall = false; - if(isUnique) recordsOver = true; - return rec; - } - //firstCall = false; - }else - { - if (nodeOffset == iter->noElements_) - { - if (NULL == iter->next_) { - recordsOver = true; - iter->mutex_.releaseShareLock(procSlot); - iter = NULL; - return NULL; - } - char* record = ((char*)iter->next_->min_)+ fldOffset; - bool result = AllDataType::compareVal(searchKey, record, - OpGreaterThanEquals, - type, length); - if (!result && (OpLessThan ==op || OpLessThanEquals == op)) - { - //Case: search key 10 , next node first record is 20 - //condition is < or <= - recordsOver= true; - iter->mutex_.releaseShareLock(procSlot); - iter = NULL; - return NULL; - }else if (result && (OpGreaterThan == op || - OpGreaterThanEquals == op)) - { - //Case: search key 20 , next node first record is 10 - //condition is > or >= - recordsOver= true; - iter->mutex_.releaseShareLock(procSlot); - iter = NULL; - return NULL; - } - TreeNode *tmpIter = iter; - iter = iter->next_; - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter, procSlot); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - tmpIter->mutex_.releaseShareLock(procSlot); - iter = NULL; - return NULL; - } - tmpIter->mutex_.releaseShareLock(procSlot); - printDebug(DM_TreeIndex,"\n Moving Node next"); - nodeOffset=0; - } - char **rec = (char**)((char*)iter + sizeof(TreeNode)); - rec = (char**)((char *)rec + ((nodeOffset) * sizeof(void **))); - nodeOffset++; - //TEMP::UNCOMMENT THIS if any issue - /*if(NULL==(*rec)) - iter->mutex_.releaseShareLock(procSlot); - */ - return *rec; - } - return NULL; -} - -void* TreeIter::locateNode() -{ - TreeNode *tnode=NULL; - TreeNode *fiter= (TreeNode *)fstLTnode; - DbRetVal ret=OK; - ret = TreeIndex::getTreeNodeMutex(fiter, procSlot); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - return NULL; - } - while( fiter!= NULL) - { - printDebug(DM_TreeIndex,"\n Search in first level start"); - tnode = (TreeNode *)*((char**)((char*)((char*)fiter + sizeof(TreeNode))+ ((fiter->noElements_-1)*sizeof(void *)))); - char *record = ((char*)tnode->max_)+ fldOffset; - bool result = AllDataType::compareVal(searchKey, record,OpLessThanEquals,type, length); - if (result) - { - break; - }else - { - printDebug(DM_TreeIndex,"\n Search in first level next"); - TreeNode* tmpIter = fiter; - if(fiter->next_!= NULL){ - fiter = fiter->next_; - ret = TreeIndex::getTreeNodeMutex(fiter, procSlot); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - tmpIter->mutex_.releaseShareLock(procSlot); - iter = NULL; - return NULL; - } - tmpIter->mutex_.releaseShareLock(procSlot); - }else{ - tmpIter->mutex_.releaseShareLock(procSlot); - fiter = NULL; - } - } - } - if(fiter == NULL) - { - iter = NULL; - return NULL; - } - //Get leaf Node - - int loc=0, middle=0, start=0, end=fiter->noElements_-1; - char **rec = (char**)((char*)fiter + sizeof(TreeNode)); - TreeNode *tNode; - if(fiter->noElements_==1) - { - tNode = ((TreeNode *)*(char**)((char*)rec + (loc * sizeof(void *)))); - iter = tNode; - fiter->mutex_.releaseShareLock(procSlot); - void *rec1 = locateElement(); - return rec1; - } - for(middle = (start + end) / 2; start <= end ; middle = (start +end )/2) - { - loc = middle; - tNode = (TreeNode *)*((char**)((char*)((char*)fiter + sizeof(TreeNode))+ (loc*sizeof(void *)))); - char *record = ((char*)tNode->max_)+ fldOffset; - - bool res = AllDataType::compareVal(searchKey, record, OpLessThan, - type, length); - if(res) - { - end = middle - 1; - } - else - { - res = AllDataType::compareVal(searchKey, record, OpGreaterThan, - type, length); - if (res) { - start = middle + 1; - loc = start; - }else { - loc = middle; - break; - } - } - } - printDebug(DM_TreeIndex,"\n Search in fisrt level end loc =%d\n",loc); - tNode = ((TreeNode *)*(char**)((char*)rec + (loc * sizeof(void *)))); - iter = tNode; - fiter->mutex_.releaseShareLock(procSlot); - void *rec1 = locateElement(); - return rec1; -} - -void* TreeIter::locateElement() -{ - //do binary search and locate the element - int loc=0, middle=0, start=0, end=iter->noElements_-1; - char **rec = (char**)((char*)iter + sizeof(TreeNode)); - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter, procSlot); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - return NULL; - } - for(middle = (start + end) / 2; start <= end ; middle = (start +end )/2) - { - loc = middle; - char *record = ((char*)*(rec+middle)) + fldOffset; - bool res = AllDataType::compareVal(searchKey, record, OpLessThan, - type, length); - if(res) - { - end = middle - 1; - } - else - { - res = AllDataType::compareVal(searchKey, record, OpGreaterThan, - type, length); - if (res) { - start = middle + 1; - loc = start; - }else { - loc = middle; - break; - } - } - } - nodeOffset=loc; - char **tuple = (char**)((char*)rec + (loc * sizeof(void *))); - nodeOffset++; - //iter->mutex_.releaseShareLock(procSlot); - return *tuple; -} diff --git a/src/storage/TreeNode.cxx b/src/storage/TreeNode.cxx deleted file mode 100644 index 32d598cc..00000000 --- a/src/storage/TreeNode.cxx +++ /dev/null @@ -1,813 +0,0 @@ -/*************************************************************************** - * 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 - -long long TreeNode::getTotalElements() -{ - DbRetVal rv=OK; - TreeNode *iter = (TreeNode *) this ; - TreeNode *tnode=NULL; - long long totalElement=0; - while(iter != NULL) - { - for(int i=0;i< iter->noElements_;i++) - { - tnode = (TreeNode *)*((char**)((char*)((char*)iter + sizeof(TreeNode))+ ((i)*sizeof(void *)))); - totalElement += tnode->noElements_; - } - iter=iter->next_; - } - return totalElement; -} - -void TreeNode::displayAll(int fldOffset) -{ - DbRetVal rv=OK; - TreeNode *iter = (TreeNode *) this ; - TreeNode *tnode=NULL; - TreeNode *prev = iter; - bool result = false; - printf("\n"); - int i=0; - while(iter != NULL) - { - i++; - tnode = (TreeNode *)*((char**)((char*)((char*)iter + sizeof(TreeNode))+ ((iter->noElements_-1)*sizeof(void *)))); - char *record = ((char*)tnode->max_)+ fldOffset; - TreeNode *needremovetnode = (TreeNode *)*((char**)((char*)((char*)iter + sizeof(TreeNode)))); - printf(" node:%d noElements:%d \n",i, iter->noElements_); - for(int i=0;i< iter->noElements_;i++) - { - tnode = (TreeNode *)*((char**)((char*)((char*)iter + sizeof(TreeNode))+ ((i)*sizeof(void *)))); - printf(" Node:%d Elements:%d Min:%d Max:%d \n ",i, tnode->noElements_, *(int*)((char*)tnode->min_+fldOffset), *(int*)((char*)tnode->max_ + fldOffset)); - char **rec= (char**)((char*)tnode + sizeof(TreeNode)); - for(int j=0; j < tnode->noElements_; j++){ - printf("%d,",*((int*)((char*) *(rec + j )+fldOffset))); - } - printf("\n"); - - } - iter=iter->next_; - } - printf("\n"); -} - -void TreeNode::displayAll() -{ - DbRetVal rv=OK; - TreeNode *iter = (TreeNode *) this ; - TreeNode *tnode=NULL; - long long totalElement=0; - int count=1; - printf("\n"); - while(iter != NULL) - { - printf(" %d %d %x %d \n", count, iter->noElements_, &iter->mutex_, iter->mutex_.getLockVal()); - for(int i=0;i< iter->noElements_;i++) - { - tnode = (TreeNode *)*((char**)((char*)((char*)iter + sizeof(TreeNode))+ ((i)*sizeof(void *)))); - printf(" %d %x %d \n",i, tnode->noElements_, &tnode->mutex_, tnode->mutex_.getLockVal()); - totalElement += tnode->noElements_; - } - iter=iter->next_; - count++; - } - printf(" %lld \n",totalElement); - printf("\n"); -} - -DbRetVal TreeNode::insertNodeIntoFirstLevel(Database * db, IndexInfo * indInfo, void* indexPtr, TreeNode * newNode,int nodepos) -{ - DbRetVal rv=OK; - TreeNode *start = (TreeNode *) this; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - int offset = info->fldOffset; - DataType type = info->type; - int noOfBuckets = info->noOfBuckets; - char **node = NULL; - char *tmp = NULL; - char *tmpnode=NULL; - TreeNode *tempNode = start; - if(start->noElements_< noOfBuckets) - { - printDebug(DM_TreeIndex,"insertNodeIntoFirstLevel after node insert manage first level node"); - if(start->noElements_<= nodepos) - { - node = (char **)((char*)start + sizeof(TreeNode) + (nodepos * sizeof(void *))); - start->noElements_++; - *node = (char*)newNode; - }else - { - node = (char**)((char*)start + sizeof(TreeNode)); - tmp = (char *)malloc(sizeof(void *) * (start->noElements_ - nodepos)); - memcpy(tmp, (char*)node + (nodepos * sizeof(void *)), sizeof(void *) * (start->noElements_ - nodepos)); - memcpy((char*)node + ((nodepos+1) * sizeof(void *)), tmp, sizeof(void *) * (start->noElements_ - nodepos)); - free(tmp); - node = (char **)((char*)node + (nodepos * sizeof(void *))); - *node = (char*)newNode; - start->noElements_++; - } - } - else - { - node = (char**)((char*)start + sizeof(TreeNode)); - if(start->noElements_ > nodepos) - { - tmpnode = *(char **)((char*)node+ ((start->noElements_-1) * sizeof(void *)));//store last one - tmp = (char *)malloc(sizeof(void *) * (start->noElements_ - nodepos)); - memcpy(tmp, (char*)node + (nodepos * sizeof(void *)), sizeof(void *) * (start->noElements_ - nodepos-1)); - memcpy((char*)node + ((nodepos+1) * sizeof(void *)), tmp, sizeof(void *) * (start->noElements_ - nodepos-1)); - free(tmp); - node = (char **)((char*)node + (nodepos * sizeof(void *))); - *node = (char*)newNode; - }else - { - tmpnode =(char*)newNode; - } - nodepos=0; - if( start->next_ != NULL && start->next_->noElements_< noOfBuckets) - { - start = start->next_; - - node = (char**)((char*)start + sizeof(TreeNode)); - tmp = (char *)malloc(sizeof(void *) * (start->noElements_ - nodepos)); - memcpy(tmp, (char*)node + (nodepos * sizeof(void *)), sizeof(void *) * (start->noElements_ - nodepos)); - memcpy((char*)node + ((nodepos+1) * sizeof(void *)), tmp, sizeof(void *) * (start->noElements_ - nodepos)); - free(tmp); - node = (char **)((char*)node + (nodepos * sizeof(void *))); - *node = (char*)tmpnode; - start->noElements_++; - start->mutex_.releaseShareLock(db->procSlot); - }else - { - printDebug(DM_TreeIndex, "Check if full and start->next_ ==NULL then create new one"); - Chunk *ftchunk = (Chunk*) iptr->chunkPtr_; - TreeNode *ftnode = (TreeNode*) ftchunk->allocate(db, &rv); - if (ftnode == NULL) - { - printError(rv, "Exit TreeNode firstlevel allocate fail"); - tempNode->mutex_.releaseShareLock(db->procSlot); - return rv; - } - ftnode->mutex_.init("TNODE-I"); - ftnode->min_= NULL; - ftnode->max_ = NULL; - ftnode->noElements_ =1; - ftnode->balance_ = 0; - char **tn=(char**)((char*) ftnode+sizeof(TreeNode)); - *tn = (char*)tmpnode; - ftnode->next_ = start->next_; - ftnode->prev_ = start; - start->next_ = ftnode; - } - } - tempNode->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",tempNode); - return OK; -} - -DbRetVal TreeNode::insertRecordIntoNodeAndArrangeFirstLevel(Database * db, IndexInfo * indInfo, void* indexPtr, void * tuple, TreeNode * fstLevel, int nodePos) -{ - TreeNode *iter = (TreeNode *) this; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - int offset = info->fldOffset; - DataType type = info->type; - int noOfBuckets = info->noOfBuckets; - void *record = NULL; - char *keyVal = (char*) tuple + info->fldOffset; - DbRetVal rc = OK; - bool recordInserted = false; - TreeNode *tmpNode=NULL; - int ret = iter->mutex_.getExclusiveLock(db->procSlot); - if (0 != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - fstLevel->mutex_.releaseShareLock(db->procSlot); //release here 1st level - return ErrLockTimeOut; - } - if(iter->noElements_>= noOfBuckets) - { - //Ist level full - //Decide new record should go in left or right of second level - //if it is inside then create new memcpy all address from location to next node - //if left check prev_ node has free space or not if yes insert at end else create new - //if right check next_ node has free space or not if yes insert at Ist loc nad do memcpy else create new - //create node and link to prevous node and link to the Fistlevel - record = ((char*)iter->max_)+ info->fldOffset; - bool result = AllDataType::compareVal(keyVal, record, OpGreaterThan, info->type, info->compLength); - if(result) - { - printDebug(DM_TreeIndex,"locateed Node full new node create at iright"); - //check right for free space if not create node right - tmpNode = iter->next_; - if(tmpNode!=NULL && tmpNode->noElements_ < noOfBuckets) - { - //insert at beginning - ret = tmpNode->mutex_.getExclusiveLock(db->procSlot); - if (0 != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); //release here 1st level - return ErrLockTimeOut; - } - char *tmp = NULL; - char **rec = (char**)((char*)tmpNode + sizeof(TreeNode)); - tmp = (char *)malloc(sizeof(void *) * (tmpNode->noElements_)); - memcpy(tmp, (char*)rec , sizeof(void *) * (iter->noElements_)); - memcpy((char*)rec + (1*sizeof(void *)), tmp, sizeof(void *) * (iter->noElements_)); - *rec = (char*)tuple; - tmpNode->min_=tuple; - tmpNode->noElements_++; - free(tmp); - iter->mutex_.releaseShareLock(db->procSlot); - tmpNode->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fstLevel); - } - else - { - //allocate new node here - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - TreeNode *tnode = (TreeNode*) chunk->allocate(db, &rc); - if (tnode == NULL) - { - printError(rc, "Exit TreeNode create fail after node full"); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fstLevel); - return rc; - } - if( fstLevel->next_!=NULL && fstLevel->noElements_>= noOfBuckets && fstLevel->next_->noElements_< noOfBuckets) - { - ret = fstLevel->next_->mutex_.getExclusiveLock(db->procSlot); - if (0 != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - chunk->free(db, tnode); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); //release here 1st level - return ErrLockTimeOut; - } - } - tnode->mutex_.init(); - strcpy(tnode->mutex_.name, "Tree"); - tnode->min_ = tuple; - tnode->max_ = tuple; - tnode->noElements_ =1; - tnode->next_ = NULL; - tnode->prev_ = NULL; - tnode->balance_ = 0; - char **rec = (char**)((char*) tnode + sizeof(TreeNode)); - *rec = (char*) tuple; - if(iter->next_!=NULL){ - if( 0 !=Mutex::CASL((long*)&iter->next_->prev_, (long)iter->next_->prev_, (long)tnode)) - { - printError(ErrLockTimeOut, "Lock timeout..retry Tree"); - chunk->free(db, tnode); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - return ErrLockTimeOut; - } - } - tnode->next_= iter->next_; - tnode->prev_= iter; - iter->next_= tnode; - nodePos++; - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->insertNodeIntoFirstLevel(db, indInfo, indexPtr, tnode, nodePos); - } - }else - { - record = ((char*)iter->min_)+ info->fldOffset; - bool result = AllDataType::compareVal(keyVal, record, OpLessThan, info->type, info->compLength); - if(result) - { - printDebug(DM_TreeIndex,"\nlocateed Node full new node create at left"); - //check left for free space if not create node left - tmpNode = iter->prev_; - if(tmpNode!=NULL && tmpNode->noElements_ < noOfBuckets) - { - //insert at End - ret = tmpNode->mutex_.getExclusiveLock(db->procSlot); - if (0 != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); //release here 1st level - return ErrLockTimeOut; - } - char **rec = (char**)((char*)tmpNode + sizeof(TreeNode)); - rec = (char **)((char *)rec + (tmpNode->noElements_ * sizeof(void *))); - *rec = (char*)tuple; - tmpNode->max_ = tuple; - tmpNode->noElements_++; - iter->mutex_.releaseShareLock(db->procSlot); - tmpNode->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fstLevel); - }else - { - //allocate here - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - TreeNode *tnode = (TreeNode*) chunk->allocate(db, &rc); - if (tnode == NULL) - { - printError(rc, "Exit TreeNode create fail after node full"); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fstLevel); - return rc; - } - if( fstLevel->next_!=NULL && fstLevel->noElements_>= noOfBuckets && fstLevel->next_->noElements_< noOfBuckets) - { - ret = fstLevel->next_->mutex_.getExclusiveLock(db->procSlot); - if (0 != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - chunk->free(db, tnode); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); //release here 1st level - return ErrLockTimeOut; - } - } - tnode->mutex_.init(); - strcpy(tnode->mutex_.name, "Tree"); - tnode->min_ = tuple; - tnode->max_ = tuple; - tnode->noElements_ =1; - tnode->next_ = NULL; - tnode->prev_ = NULL; - tnode->balance_ = 0; - char **rec = (char**)((char*) tnode + sizeof(TreeNode)); - printDebug(DM_TreeIndex, "Storing first record at %x\n", rec); - *rec = (char*) tuple; - if(iter->prev_!=NULL) { - if( 0 !=Mutex::CASL((long*)&iter->prev_->next_, (long)iter->prev_->next_, (long)tnode)) - { - printError(ErrLockTimeOut, "Lock timeout..retry Tree"); - chunk->free(db, tnode); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - return ErrLockTimeOut; - } - } - tnode->prev_= iter->prev_; - tnode->next_= iter; - iter->prev_= tnode; - //manage First level - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->insertNodeIntoFirstLevel(db, indInfo, indexPtr, tnode, nodePos); - } - }else - { - //create right - //locate position shift node - void *tmprec=NULL; - char **rec = (char**)((char*) iter + sizeof(TreeNode)); - tmprec = iter->max_; - int start = 0; - int end = iter->noElements_ - 1; - int middle; - int loc = 0; - char *tmp = NULL; - loc=0; - for(middle = (start + end) / 2; start <= end ; middle = (start +end )/2) - { - loc = middle; - record = ((char*)*(rec+middle)) + info->fldOffset; - printDebug(DM_TreeIndex, "%d-%d\n\n", *((int*)keyVal), *((int*)record)); - bool res = AllDataType::compareVal(keyVal, record, - OpLessThan, info->type, info->compLength); - if(res) - { - end = middle - 1; - } - else - { - res = AllDataType::compareVal(keyVal, record, - OpGreaterThan, info->type, info->compLength); - if (res) { - start = middle + 1; - loc = start; - }else { - loc = middle; - if (info->isUnique) { - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - printError(ErrUnique, "Unique constraint violation"); - return ErrUnique; - } - break; - } - } - } - - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - TreeNode *tnode = (TreeNode*) chunk->allocate(db, &rc); - if (tnode == NULL) - { - printError(rc, "Exit TreeNode create fail after node full"); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",fstLevel); - return rc; - } - if( fstLevel->next_!=NULL && fstLevel->noElements_>= noOfBuckets && fstLevel->next_->noElements_< noOfBuckets) - { - ret = fstLevel->next_->mutex_.getExclusiveLock(db->procSlot); - if (0 != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - chunk->free(db, tnode); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); //release here 1st level - return ErrLockTimeOut; - } - } - tnode->mutex_.init(); - strcpy(tnode->mutex_.name, "Tree"); - tnode->min_ = tuple; - tnode->max_ = tuple; - tnode->noElements_ =1; - tnode->next_ = NULL; - tnode->prev_ = NULL; - tnode->balance_ = 0; - - //shift all element from the location to next node - char **fstRec = (char**)((char*)iter + sizeof(TreeNode)); - tmp = (char *)malloc(sizeof(void *) * (iter->noElements_ - loc)); - memcpy(tmp, (char*)fstRec+ (loc * sizeof(void *)), sizeof(void *) * (iter->noElements_ - loc)); - rec = (char **)((char*)fstRec + (loc * sizeof(void *))); - *rec = (char*)tuple; - //copy to next node - fstRec = (char**)((char*) tnode + sizeof(TreeNode)); - memcpy((char*)fstRec, tmp, sizeof(void *) * (iter->noElements_- loc)); - free(tmp); - tnode->noElements_= iter->noElements_- loc; - tnode->max_= tmprec; - tnode->min_= *fstRec; - iter->noElements_= loc + 1; - iter->max_= tuple; - if(loc==0) - { - iter->min_ = tuple; - } - if(iter->next_!=NULL){ - if( 0 !=Mutex::CASL((long*)&iter->next_->prev_, (long)iter->next_->prev_, (long)tnode)) - { - printError(ErrLockTimeOut, "Lock timeout..retry Tree"); - chunk->free(db, tnode); - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->mutex_.releaseShareLock(db->procSlot); - return ErrLockTimeOut; - } - } - tnode->next_= iter->next_; - tnode->prev_=iter; - iter->next_=tnode; //TODO::need here CASL - nodePos++; - //shift right done after this block - printDebug(DM_TreeIndex,"located Node full new node create at right position %d shift node",loc); - //manage First level - iter->mutex_.releaseShareLock(db->procSlot); - fstLevel->insertNodeIntoFirstLevel(db, indInfo, indexPtr, tnode, nodePos); - } - } - return OK; - } - if(iter->noElements_< noOfBuckets) - { - fstLevel->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex,"located Node not full insert in same node"); - - record = ((char*)iter->max_)+ info->fldOffset; - printDebug(DM_TreeIndex, "\n%d---%d", *((int*)keyVal), *((int*)record)); - bool result = AllDataType::compareVal(keyVal, record, OpGreaterThan, info->type, info->compLength); - if(result) - { - char **rec = (char**)((char*)iter + sizeof(TreeNode)); - rec = (char **)((char *)rec + (iter->noElements_ * sizeof(void **))); - iter->max_ = tuple; - iter->noElements_++; - *rec = (char*) tuple; - } - else - { - int start = 0; - int end = iter->noElements_ - 1; - int middle; - int loc = 0; - char **rec = (char**)((char*)iter + sizeof(TreeNode)); - char *tmp = NULL; - loc=0; - for(middle = (start + end) / 2; start <= end ; middle = (start +end )/2) - { - loc = middle; - record = ((char*)*(rec+middle)) + info->fldOffset; - printDebug(DM_TreeIndex, "%d-%d\n\n", *((int*)keyVal), *((int*)record)); - bool res = AllDataType::compareVal(keyVal, record, OpLessThan, info->type, info->compLength); - if(res) - { - end = middle - 1; - } - else - { - res = AllDataType::compareVal(keyVal, record, OpGreaterThan, info->type, info->compLength); - if (res) { - start = middle + 1; - loc = start; - }else { - loc = middle; - if (info->isUnique) - { - iter->mutex_.releaseShareLock(db->procSlot); - //fstLevel->mutex_.releaseShareLock(db->procSlot); - printError(ErrUnique, "Unique constraint violation"); - return ErrUnique; - } - break; - } - } - } - printDebug(DM_TreeIndex, "\nInsert pos-%d",loc); - rec = (char**)((char*)iter + sizeof(TreeNode)); - tmp = (char *)malloc(sizeof(void *) * (iter->noElements_ - loc)); - memcpy(tmp, (char*)rec + (loc * sizeof(void *)), sizeof(void *) * (iter->noElements_ - loc));///////// Check the type cast char * - memcpy((char*)rec + ((loc+1) * sizeof(void *)), tmp, sizeof(void *) * (iter->noElements_ - loc)); - free(tmp); - if(loc==0) - { - iter->min_ = tuple; - } - iter->noElements_++; - rec = (char **)((char*)rec + (loc * sizeof(void *))); - *rec = (char*)tuple; - } - //first level mutex release - iter->mutex_.releaseShareLock(db->procSlot); - } - return OK; -} - -DbRetVal TreeNode::insert(Database *db,IndexInfo *indInfo,void *indexPtr,void *tuple) -{ - DbRetVal rv=OK; - TreeNode *iter = (TreeNode *) this ; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - void *searchKey =(void*)((char*)tuple + info->fldOffset); - TreeNode *tnode=NULL; - TreeNode *prev = iter; - bool result = false; - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter, db->procSlot, true); - if (OK != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - return ErrLockTimeOut; - } - printDebug(DM_TreeIndex," Tree I Level Mutex Taken on %x\n",iter); - - while(iter != NULL ) - { - //get the second level last node as min and max are not stored in first level tree node - tnode = (TreeNode *)*((char**)((char*)((char*)iter + sizeof(TreeNode))+ ((iter->noElements_-1)*sizeof(void *)))); - char *record = ((char*)tnode->max_)+ info->fldOffset; - result = AllDataType::compareVal(searchKey, record,OpLessThanEquals,info->type, info->compLength); - if (result) - { - break; - }else - { - if(tnode->noElements_ >= info->noOfBuckets) - { - if(iter->next_!=NULL) - { - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter->next_, db->procSlot, true); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - iter->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Tree I Level Mutex Release on %x\n",iter); - return ErrLockTimeOut; - } - printDebug(DM_TreeIndex," Tree I Level Mutex Taken on %x\n",iter->next_); - prev = iter; - iter = iter->next_; - prev->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Tree I Level Mutex Release on %x\n",prev); - }else{ - prev = iter; - iter = iter->next_; - } - }else - { - if(iter->next_!=NULL) - { - tnode = (TreeNode *)*((char**)((char*)((char*)iter->next_ + sizeof(TreeNode)))); - char *record = ((char*)tnode->min_)+ info->fldOffset; - result = AllDataType::compareVal(searchKey, record,OpLessThan,info->type, info->compLength); - if (result) - { - break; - } else - { - //if(iter->next_!=NULL) - { - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter->next_, - db->procSlot, true); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - iter->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",iter); - return ErrLockTimeOut; - } - printDebug(DM_TreeIndex," Mutex Taken on %x\n",iter); - prev = iter; - iter = iter->next_; - prev->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",prev); - } - /*else - { - prev = iter; - iter = iter->next_; - }*/ - } - }else{ - break; - } - } - } - } - //iter will be null if the value being inserted is greater - //than the last I-level node's II-level last node's max - if( iter == NULL && prev->noElements_< info->noOfBuckets) - { - iter = prev ; - } - if(iter == NULL) - { - //TODO::Put this is another function and use the same from 1st record insert - //create Ist level node then leaf node ,insert record and return - printDebug(DM_TreeIndex, "iter =NULL create Ist level node then leaf node ,insert record and return"); - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - TreeNode *tnode = (TreeNode*) chunk->allocate(db, &rv); - if (tnode == NULL) - { - printError(rv, "Exit TreeNode allocate fail"); - return rv; - } - tnode->mutex_.init(); - strcpy(tnode->mutex_.name, "Tree"); - tnode->min_ = tuple; - tnode->max_ = tuple; - tnode->noElements_ =1; - tnode->next_ = NULL; - tnode->prev_ = NULL; - tnode->balance_ = 0; - char **rec = (char**)((char*) tnode + sizeof(TreeNode)); - printDebug(DM_TreeIndex, "Storing first record at %x\n", rec); - *rec = (char*) tuple; - TreeNode *prevNode = (TreeNode*)*(char**)((char*) prev +sizeof(TreeNode)+((prev->noElements_-1)* sizeof(void*))); - prevNode->next_= tnode; - tnode->prev_= prevNode; - //fist levelnode - Chunk *ftchunk = (Chunk*) iptr->chunkPtr_; - TreeNode *ftnode = (TreeNode*) ftchunk->allocate(db, &rv); - if (ftnode == NULL) - { - printDebug(DM_TreeIndex, "Exit TreeNode firstlevel allocate fail"); - return rv; - } - ftnode->mutex_.init("TNODE-I"); - ftnode->min_= NULL; - ftnode->max_ = NULL; - ftnode->noElements_ =1; - ftnode->next_ = NULL; - ftnode->balance_ = 0; - char **tn=(char**)((char*) ftnode+sizeof(TreeNode)); - *tn = (char*)tnode; - ftnode->prev_= prev; - prev->next_=ftnode; - prev->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",prev); - return OK; - } - //Get second level node and node position from the - //first level node identified above as 'iter' - int nodepos=0; - tnode = locateNodeFromFirstLevel(iter, indInfo, tuple, &nodepos); - //first level mutex is taken and it is released in the below function - //This is because in case arrangement in first level node when it is full - //then subsequent first level node mutex is taken and current first level node - //mutex is released - rv = tnode->insertRecordIntoNodeAndArrangeFirstLevel(db, indInfo, indexPtr, tuple, iter, nodepos); - return rv; -} - -TreeNode* TreeNode::locateNode(Database *db, TreeNode *iter, void *tuple, IndexInfo *indInfo,DbRetVal &rv) -{ - if(iter == NULL) return NULL; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - void *searchKey =(void*)((char*)tuple + info->fldOffset); - TreeNode *tnode=NULL; - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter, db->procSlot, true); - if (OK != ret) { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - rv = ErrLockTimeOut; - return NULL; - } - printDebug(DM_TreeIndex," Mutex Taken on %x\n",iter); - TreeNode *tmpNode=NULL; - while(iter->noElements_>= info->noOfBuckets && iter != NULL) - { - tnode = (TreeNode *)*((char**)((char*)iter + sizeof(TreeNode)+ ((iter->noElements_-1)*sizeof(void *)))); - char *record = ((char*)tnode->max_)+ info->fldOffset; - bool result = AllDataType::compareVal(searchKey, record,OpLessThanEquals,info->type, info->compLength); - if (result) - { - break; - }else - { - if(iter->next_!=NULL) - { - DbRetVal ret = TreeIndex::getTreeNodeMutex(iter->next_, db->procSlot, true); - if (OK != ret) - { - printError(ErrLockTimeOut,"Unable to lock the tree node. Retry..."); - iter->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",iter); - rv = ErrLockTimeOut; - return NULL; - } - printDebug(DM_TreeIndex," Mutex Taken on %x\n",iter->next_); - tmpNode = iter; - iter = iter->next_; - tmpNode->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",tmpNode); - }else{ - iter->mutex_.releaseShareLock(db->procSlot); - printDebug(DM_TreeIndex," Mutex Release on %x\n",iter); - iter = iter->next_; - } - } - } - //Get leaf Node - return iter; - -} - -TreeNode *TreeNode::locateNodeFromFirstLevel(TreeNode *ftnode, IndexInfo *indInfo,void *tuple, int *pos) -{ - HashIndexInfo *info = (HashIndexInfo*) indInfo; - int fldOffset = info->fldOffset; - DataType type = info->type; - int length = info->compLength; - void *searchKey =(void*)((char*)tuple + info->fldOffset); - int loc=0, middle = 0, start = 0, end = ftnode->noElements_-1; - char **node = (char**)((char*)ftnode + sizeof(TreeNode)); - TreeNode *tNode; - for(middle = (start + end) / 2; start <= end ; middle = (start +end )/2) - { - loc = middle; - char *record =(char *)(((TreeNode *) *(char**)((char*)node + (loc * sizeof(void *))))->max_)+fldOffset; - - bool res = AllDataType::compareVal(searchKey, record, OpLessThan,type, length); - if(res) - { - end = middle - 1; - } - else - { - res = AllDataType::compareVal(searchKey, record, OpGreaterThan, type, length); - if (res) { - start = middle + 1; - if(start <= (ftnode->noElements_-1)) loc = start; - }else { - loc=middle; - break; - } - } - } - printDebug(DM_TreeIndex, "inside locateNodeFromFirstLevel loc=%d",loc); - *pos=loc; - tNode = ((TreeNode *)*(char**)((char*)node + (loc * sizeof(void *)))); - return tNode; -} diff --git a/src/storage/TrieIndex.cxx b/src/storage/TrieIndex.cxx deleted file mode 100644 index 127c1a97..00000000 --- a/src/storage/TrieIndex.cxx +++ /dev/null @@ -1,399 +0,0 @@ -/*************************************************************************** - * 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 - -//converts the given value into 0 to TRIE_SIZE -//value could be 0-9, A-Z, a-z and special chars -char hashString(char value) -{ - if (value > 47 && value <58) return value - 48; - else if (value > 64 && value <91 ) return (value - 64)/3; - else if (value > 96 && value <123) return (value - 96)/3; - //for all special and other chars return 9 - return 9; -} - -void TrieIndex::computeHashValues(DataType type, void *key, char *in, int length) -{ - if (typeInt == type ) { - int val = *(int*)key; - sprintf(in, "%d", val); - int i=0; - while (in[i] != '\0') - { - in[i] = hashString(in[i]); - printDebug(DM_TrieIndex, "Hash Value Pos:%d Hash:%d\n", i, in[i]); - i++; - } - in[i] = -1; - }else if (typeLongLong == type) { - long val = *(long*)key; - sprintf(in, "%lld", val); - int i=0; - while (in[i] != '\0') - { - in[i] = hashString(in[i]); - printDebug(DM_TrieIndex, "Hash Value Pos:%d Hash:%d\n", i, in[i]); - i++; - } - in[i] = -1; - }else if (typeString == type || typeVarchar == type) { - char *val = (char*) key; - int i=0; - while (*val != '\0') - { - in[i] = hashString(*val); - printDebug(DM_TrieIndex, "Hash Value Pos:%d Hash:%d\n", i, in[i]); - val++; - i++; - } - in[i] = (char)-1; - }else - printError(ErrSysFatal,"Type not supported for trie hashing\n"); - return ; -} - -bool TrieIndex::checkForUniqueKey(IndexNode *head, IndexInfo *info, void *tuple) -{ - if (!head) return false; - int offset = info->fldOffset; - DataType type = info->type; - BucketList list(head); - BucketIter iter = list.getIterator(); - IndexNode *node; - void *bucketTuple; - printDebug(DM_TrieIndex, "TrieIndex insert Checking for unique"); - bool res = false; - while((node = iter.next()) != NULL) - { - bucketTuple = node->ptrToTuple_; - if (type != typeVarchar) - res = AllDataType::compareVal((void*)((char*)bucketTuple +offset), - (void*)((char*)tuple +offset), OpEquals,type, info->compLength); - else - res = AllDataType::compareVal((void*)*(long *)((char*)bucketTuple +offset), - (void*)*(long *)((char*)tuple +offset), OpEquals,type, info->compLength); - if (res) - { - printError(ErrUnique, "Unique key violation"); - return true; - } - } - return false; -} - - -DbRetVal TrieIndex::insert(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool loadFlag) -{ - DbRetVal rv = OK; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - char hashValue[TRIE_MAX_LENGTH]; - void *keyPtr =(void*)((char*)tuple + info->fldOffset); - //for varchar ptr to value is stored in tuple - if (info->type == typeVarchar) keyPtr = (void *) *(long *) keyPtr; - computeHashValues(info->type, keyPtr, hashValue, info->compLength); - Chunk *hIdxNodeChunk = (Chunk*)iptr->hashNodeChunk_; - Chunk *chunk = (Chunk*) iptr->chunkPtr_; - ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); - TrieNode* start = (TrieNode*)citer.nextElement(); - //if(start) displayAll(start); - int cnt=0; - if (NULL == start) { - //first value is inserted into the trie index - start = (TrieNode*) chunk->tryAllocate(tbl->db_, &rv); - if (NULL == start) { - printError(ErrSysInternal, "Could not allocate trie node %d\n", rv); - return rv; - } - } - char **prev = NULL; - while(-1 != hashValue[cnt+1]) { - prev = (char**)&(start->next_[hashValue[cnt]]); - if (*prev) - { - start = (TrieNode*) *prev; - cnt++; - continue; - } - //allocate trie node - TrieNode *newNode = (TrieNode*) chunk->tryAllocate(tbl->db_, &rv); - if (NULL == newNode) { - printError(ErrSysInternal, "Could not allocate trie node %d\n", rv); - return rv; - } - //set the previous trie node ptr to this node - *prev = (char*)newNode; - start = newNode; - cnt++; - } - void **ptr = (void**)&(start->head_[hashValue[cnt]]); - rv = addToValueList(tbl->db_, ptr, hIdxNodeChunk, indInfo, tuple, keyPtr); - if (OK != rv) return rv; - - //create logical undo log - TrieUndoLogInfo hInfo; - hInfo.metaData_ = tbl->db_->getMetaDataPtr(); - hInfo.bucketPtr_ = ptr; - hInfo.tuple_ = tuple; - hInfo.keyPtr_ = keyPtr; - hInfo.hChunk_ = hIdxNodeChunk; - - if (!loadFlag) { - rv = tr->appendLogicalTrieUndoLog(tbl->sysDB_, InsertTrieIndexOperation, &hInfo, sizeof(TrieUndoLogInfo)); - //TODO:: if it fails need to remove the element from the bucket - } - return rv; -} - -DbRetVal TrieIndex::addToValueList(Database *db, void **ptr, Chunk *hIdxNodeChunk, - IndexInfo *info, void *tuple, void *keyPtr) -{ - IndexNode *head = (IndexNode*) *ptr; - if (info->isUnique) - { - bool isKeyPresent = checkForUniqueKey(head, info, tuple); - if (isKeyPresent) return ErrUnique; - } - printDebug(DM_TrieIndex, "TrieIndex insert into bucket list"); - DbRetVal rv = OK; - if (!head) - { - printDebug(DM_TrieIndex, "TrieIndex insert head is empty"); - IndexNode *firstNode= NULL; - firstNode= (IndexNode*) hIdxNodeChunk->tryAllocate(db, &rv); - if (firstNode == NULL){ - printError(rv, "Unable to allocate index node for Trie index after retry"); - return rv; - } - firstNode->ptrToKey_ = keyPtr; - firstNode->ptrToTuple_ = tuple; - firstNode->next_ = NULL; - if (0 != Mutex::CASL((long*)ptr, 0, (long)firstNode)) { - printError(ErrLockTimeOut, "Trie Index bucket lock timeout.. retry"); - hIdxNodeChunk->free(db, firstNode); - return ErrLockTimeOut; - } - printDebug(DM_TrieIndex, "TrieIndex insert new node %x in empty bucket", head); - } - else - { - BucketList list(head); - rv = list.insert(hIdxNodeChunk, db, keyPtr, tuple); - if (rv !=OK) { - printError(rv, "unable to insert into Trie bucketlist rv:%d", rv); - return rv; - } - } - return OK; -} - -DbRetVal TrieIndex::removeFromValueList(Database *db, void **ptr, Chunk *hIdxNodeChunk, void *tuple, void *keyPtr) -{ - IndexNode *head = (IndexNode*) *ptr; - printDebug(DM_TrieIndex, "TrieIndex remove from bucket list"); - DbRetVal rv = OK; - if (!head) - { - rv = ErrSysFatal; - printError(rv, "Fatal:Trie value list head is empty"); - return rv; - } - else - { - BucketList list(head); - rv = list.remove(hIdxNodeChunk, db, keyPtr); - if (SplCase == rv) - { - rv = OK; - printDebug(DM_TrieIndex, "Removing trie index node from head "); - if (0 != Mutex::CASL((long*)ptr, - (long)head, (long)list.getBucketListHead())) { - printError(ErrSysFatal, "Lock time out for trie bucket. retry\n"); - return ErrLockTimeOut; - } - } - if (rv !=OK) { - printError(rv, "unable to remove from Trie bucketlist rv:%d", rv); - return rv; - } - } - return OK; - -} - -DbRetVal TrieIndex::remove(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool loadFlag) -{ - DbRetVal rv = OK; - HashIndexInfo *info = (HashIndexInfo*) indInfo; - CINDEX *iptr = (CINDEX*)indexPtr; - char hashValue[TRIE_MAX_LENGTH]; - void *keyPtr =(void*)((char*)tuple + info->fldOffset); - Chunk *hIdxNodeChunk = (Chunk*)iptr->hashNodeChunk_; - //for varchar ptr to value is stored in tuple - if (info->type == typeVarchar) keyPtr = (void *) *(long *) keyPtr; - computeHashValues(info->type, keyPtr, hashValue, info->compLength); - ChunkIterator citer = CatalogTableINDEX::getIterator(indexPtr); - TrieNode* start = (TrieNode*)citer.nextElement(); - int cnt=0; - if (NULL == start) { - printError(ErrSysInternal, "No trie nodes found %d\n", rv); - return rv; - } - char **iter = NULL; - while(-1 != hashValue[cnt+1]) { - iter = (char**)&(start->next_[hashValue[cnt]]); - if (! *iter) - { - printError(ErrNotFound, "No trie node found %d\n", rv); - return ErrNotFound; - } - //traverse till the end - start = (TrieNode*) *iter; - cnt++; - } - void **ptr = (void**)&(start->head_[hashValue[cnt]]); - rv = removeFromValueList(tbl->db_, ptr, hIdxNodeChunk, tuple, keyPtr); - if (OK != rv) return rv; - - //create logical undo log - TrieUndoLogInfo hInfo; - hInfo.metaData_ = tbl->db_->getMetaDataPtr(); - hInfo.bucketPtr_ = ptr; - hInfo.tuple_ = tuple; - hInfo.keyPtr_ = keyPtr; - hInfo.hChunk_ = hIdxNodeChunk; - - if (!loadFlag) { - rv = tr->appendLogicalTrieUndoLog(tbl->sysDB_, DeleteTrieIndexOperation, &hInfo, sizeof(TrieUndoLogInfo)); - //TODO:: if it fails need to remove the element from the bucket - } - return rv; -} - -DbRetVal TrieIndex::update(TableImpl *tbl, Transaction *tr, void *indexPtr, IndexInfo *indInfo, void *tuple, bool loadFlag) -{ - DbRetVal rv = OK; - printError(ErrNotYet, "Not Yet Implemented"); - return rv; -} - -DbRetVal TrieIndex::insertLogicalUndoLog(Database *sysdb, void *data) -{ - TrieUndoLogInfo *info = (TrieUndoLogInfo *) data; - Chunk *hChunk = (Chunk *) info->hChunk_; - Database db; - db.setMetaDataPtr((DatabaseMetaData *) info->metaData_); - db.setProcSlot(sysdb->procSlot); - void **bkt = info->bucketPtr_; - IndexNode *head = (IndexNode *)*bkt; - BucketList list(head); - DbRetVal rv = OK; - if (!head) - { - printDebug(DM_TrieIndex, "TrieIndex insert head is empty"); - IndexNode *firstNode= NULL; - firstNode= (IndexNode*) hChunk->tryAllocate(sysdb, &rv); - if (firstNode == NULL){ - printError(rv, "Unable to allocate index node for Trie index after retry"); - return rv; - } - firstNode->ptrToKey_ = info->keyPtr_; - firstNode->ptrToTuple_ = info->tuple_; - firstNode->next_ = NULL; - if (0 != Mutex::CASL((long*)bkt, 0, (long)firstNode)) { - printError(ErrLockTimeOut, "Trie Index bucket lock timeout.. retry"); - hChunk->free(sysdb, firstNode); - return ErrLockTimeOut; - } - printDebug(DM_TrieIndex, "TrieIndex insert new node %x in empty bucket", head); - return OK; - } - - rv = list.insert(hChunk, sysdb, info->keyPtr_, info->tuple_); - if (rv != OK) - { - printError(ErrLockTimeOut, "Unable to add to bucket..retry\n"); - return ErrLockTimeOut; - } - return OK; -} - -DbRetVal TrieIndex::deleteLogicalUndoLog(Database *sysdb, void *data) -{ - TrieUndoLogInfo *info = (TrieUndoLogInfo *) data; - Chunk *hChunk = (Chunk *) info->hChunk_; - Database db; - db.setMetaDataPtr((DatabaseMetaData *)info->metaData_); - db.setProcSlot(sysdb->procSlot); - void **bkt = info->bucketPtr_; - IndexNode *head = (IndexNode *)*bkt; - BucketList list(head); - DbRetVal rc = list.remove(hChunk, &db, info->keyPtr_); - *bkt = list.getBucketListHead(); - if (SplCase == rc) { - if (0 != Mutex::CASL((long*)bkt, - (long)*bkt, - (long)list.getBucketListHead())) - { - printError(ErrLockTimeOut, "Unable to set the head of trie index bucket\n"); - return ErrLockTimeOut; - } - - }else if (rc != OK) { - printError(ErrLockTimeOut, "Unable to remove trie index node"); - return ErrLockTimeOut; - } - return OK; -} - -void TrieIndex::displayAll(TrieNode *start, int level) -{ - printTrieNode(start, level); - level++; - for (int i=0; i < TRIE_SIZE; i++) - { - if (start->next_[i]) displayAll(start->next_[i], level); - } -} - -void TrieIndex::printTrieNode(TrieNode *node, int level) -{ - printf("Trie %x Level %d child:", node, level); - for (int i=0; i < TRIE_SIZE; i++) - { - printf("%x ", node->next_[i]); - } - printf("bucket:", node); - for (int i=0; i < TRIE_SIZE; i++) - { - printf("%x ", node->head_[i]); - if ( node->head_[i]) { - printf("{ "); - BucketList list(node->head_[i]); - list.print(); - printf("} "); - } - } - printf("\n"); -} -- 2.11.4.GIT