📄 exec.c
字号:
case TK_GE:
case TK_GT:
case TK_NE:
case TK_EQ:{
pE = pE->pLeft;
idxPage = pE->iIndex;
if(pE->iIndex > 0){
int j;
/*
** if the index has opened
** then do not open again
*/
for(j=base;j<nCur;j++){
if(aiCur[j] == pE->iIndex){
pE->iIndex = j;
break;
}
}
if(j < nCur) continue;
rc = eDbBtreeCursor(db->pBt,idxPage,1,&db->pCur[nCur]);
if(rc) nErr++;
aiCur[nCur] = pE->iIndex;
pE->iIndex = nCur++;
}
break;
}
default:{
nErr ++;
}
}
if(nErr) break;
} /* end for(i=0;i<aCExpr.nExpr;i++)*/
*iCur = nCur;
return nErr;
}
/*
** open all tables with db->pCur[i],
** return 0 if success and set SrcList.a[].iCursor to i,
** return >0 if any error occured
*/
int openTables(eDb *db, SrcList *pSrc, int *iCur){
int i,rc,nErr;
int nCur;
Table *pTable;
nErr = 0;
nCur = *iCur;
for(i=0;i<pSrc->nSrc;i++){
pTable = pSrc->a[i].pTab;
rc = eDbBtreeCursor(db->pBt,pTable->tnum,0,&db->pCur[nCur++]);
if( rc ){
nErr ++;
break;
}
pSrc->a[i].iCursor = i;
}
*iCur = nCur;
return nErr;
}
/*
** get a key id
*/
int getKeyID(eDb *db,BtCursor *pCur){
int zKey;
int rc,res;
if(!db->nextRowidValid){
rc = eDbBtreeLast(pCur,&res);
if(res){
zKey = 1;
}
else{
eDbBtreeKey(pCur,0,sizeof(int),(char *)&zKey);
zKey = keyToInt(zKey)+1;
}
assert(zKey < 0x7fffffff);
db->nextRowid = zKey+1;
db->nextRowidValid = 1;
}
else{
zKey = db->nextRowid++;
}
zKey = intToKey(zKey);
return zKey;
}
/*
** make a KeyData structure
*/
KeyData *makeOneTupleRec(BtCursor *pCur, int zKey, int flag,ParseResult *pRes){
char **aCol;
int i,j;
Table *pTab;
IdList *pIdList;
ExprList *pEList;
KeyData *pTuple;
pTab = pRes->pTable;
pIdList = pRes->pIdList;
pEList = pRes->pEList;
aCol = eDbMalloc(sizeof(char *) * pTab->nCol);
if( aCol == 0){
return 0;
}
for(i=0;i<pTab->nCol;i++){
if(pIdList){
/*
** get the column values from ExprList
**
*/
for(j=0;j<pIdList->nId;j++){
if(pIdList->a[j].idx == i){
eDbSetNString(&aCol[i],
pEList->a[j].pExpr->token.z,
pEList->a[j].pExpr->token.n,0
);
eDbDequote(aCol[i]);
break;
}
}
if(j >= pIdList->nId){
/*
** if the column id not exists
** then get it from old value [in UPDATE] or
** set it NULL [in INSERT]
*/
if(flag == TK_UPDATE)
aCol[i] = eDbBtreeGetColumnData(pCur,i,0);
else
aCol[i] = 0;
}
}else{
eDbSetNString(&aCol[i],
pEList->a[i].pExpr->token.z,
pEList->a[i].pExpr->token.n,0
);
eDbDequote(aCol[i]);
}
if(eDb_malloc_failed) break;
}
if( eDb_malloc_failed ){
pTuple = 0;
}else{
if(pTab->hasPrimKey && pTab->iPKey >= 0){
zKey = atoi(aCol[pTab->iPKey]);
zKey = intToKey(zKey);
}
pTuple = fillKeyData(zKey,aCol,pTab->nCol);
}
for(j=0; j < i; j++){
eDbFree(aCol[j]);
}
eDbFree(aCol);
return pTuple;
}
KeyData *makeIdxKey(BtCursor *pCur, Index *pIdx,
int zKey,int flag,ParseResult *pRes){
int i,j,k;
int nByte;
int newidx;
char **aCol;
IdList *pIdList;
ExprList *pExpr;
Table *pTab;
KeyData *pTuple;
pTab = pIdx->pTable;
pIdList = pRes->pIdList;
pExpr = pRes->pEList;
nByte = 0;
newidx = 0;
aCol = eDbMalloc(sizeof(char *) * pIdx->nColumn);
for(i=0; i<pIdx->nColumn; i++){
if(eDb_malloc_failed) break;
if(pIdList){
/*
** find the idx column in table
*/
for(j=0;j<pIdList->nId;j++){
if(pIdList->a[j].idx == pIdx->aiColumn[i]){
newidx = 1;
eDbSetNString(&aCol[i],
pExpr->a[j].pExpr->token.z,
pExpr->a[j].pExpr->token.n,0
);
eDbDequote(aCol[i]);
nByte += strlen(aCol[i]);
break;
}else{
aCol[i] = 0;
}
}
}else{
/*
** no column name
** if the op is insert, then get the value from Expr
** else if op is update, then get the value from old value
*/
if( flag == TK_INSERT ){
newidx = 1;
j = pIdx->aiColumn[i];
eDbSetNString(&aCol[i],
pExpr->a[j].pExpr->token.z,
pExpr->a[j].pExpr->token.n,0
);
eDbDequote(aCol[i]);
}else{
aCol[i] = eDbBtreeGetColumnData(pCur,i,0);
}
nByte += strlen(aCol[i]);
}
}
if(eDb_malloc_failed || !newidx) {
/*
** the memory fail to malloc
** or the index not changed
*/
for(j=0;j<i;j++){
eDbFree(aCol[j]);
}
eDbFree(aCol);
pTuple = 0;
}else{
pTuple = eDbMalloc(sizeof(KeyData));
pTuple->nKey = nByte + 1 + sizeof(int);
pTuple->pKey = eDbMalloc(pTuple->nKey);
j = 0;
for(i=0;i<pIdx->nColumn;i++){
/*
int t = pTab->aCol[pIdx->aiColumn[i]].type;
if(t != eDb_SO_TEXT){
double r;
char z[32];
r = eDbAtoF(aCol[i],0);
eDbRealToSortable(r,z);
k = strlen(z)+1;
pData->pKey[j++] = 'b';
memcpy(&pData->pKey[j],z,k);
}
else{
k = strlen(aCol[i])+1;
pData->pKey[j++] = 'c';
memcpy(&pData->pKey[j],aCol[i],k);
}
*/
k = strlen(aCol[i]);
memcpy(&pTuple->pKey[j],aCol[i],k);
j += k;
eDbFree(aCol[i]);
}
memcpy(&pTuple->pKey[j+1],&zKey,sizeof(int));
eDbFree(aCol);
}
return pTuple;
}
int dmleDbInsert(eDb *db,ParseResult *pRes, int *nCur){
int rc;
int iTable;
int zKey;
int iCur;
int base;
Table *pTab;
Index *pIdx;
IdList *pId;
ExprList *pExpr;
KeyData *pTuple, *pIdxTuple;
pTab = pRes->pTable;
pId = pRes->pIdList;
pExpr = pRes->pEList;
pIdx = pTab->pIndex;
iTable = pTab->tnum;
iCur = base = *nCur;
rc = eDbBtreeCursor(db->pBt,iTable,1,&db->pCur[iCur++]);
if( rc ) {
goto err_handle;
}
/*
** make tuple and insert into table
*/
zKey = getKeyID(db,db->pCur[base]);
pTuple = makeOneTupleRec(db->pCur[base],zKey,TK_INSERT,pRes);
if(pTuple == 0){
goto err_handle;
}
memcpy(&zKey,pTuple->pKey,SIZEOFINT);
/*
** insert the idx key to index table
*/
for(;pIdx;pIdx=pIdx->pNext,iCur++){
rc = eDbBtreeCursor(db->pBt,pIdx->tnum,1,&db->pCur[iCur]);
if( rc ){
goto err_handle;
}
pIdxTuple = makeIdxKey(db->pCur[iCur],pIdx,zKey,TK_INSERT,pRes);
if(pIdxTuple == 0) continue;
if(pIdx->unique == OP_Unique){
rc = eDbLookupTupleByIdxKey(db->pCur[iCur],
pIdxTuple->pKey,pIdxTuple->nKey,
SIZEOFINT,TK_EQ);
/* go error if no unique*/
if( rc ){
eDbFreeKayData(pIdxTuple);
goto err_handle;
}
}
rc = eDbBtreeInsert(db->pCur[iCur],
pIdxTuple->pKey,pIdxTuple->nKey,0,0);
eDbFreeKayData(pIdxTuple);
if( rc ) {
goto err_handle;
}
}
if(pTab->hasPrimKey && pTab->iPKey >= 0){
int res;
rc = eDbBtreeMoveto(db->pCur[base],pTuple->pKey,pTuple->nKey,&res);
if( res==0 || rc ){
rc = 1;
goto err_handle;
}
}
rc = eDbBtreeInsert(db->pCur[base],
pTuple->pKey, pTuple->nKey,
pTuple->pData, pTuple->nData);
if( rc ) {
goto err_handle;
}
eDbFreeKayData(pTuple);
err_handle:
*nCur = iCur;
return rc;
}
int dmleDbUpdate(eDb *db,ParseResult *pRes, int *nCur){
int rc,res;
int iTable;
int iCur;
int base;
int nRec = 0;
Table *pTab;
Index *pIdx;
Expr *pWhere;
IdList *pIdList;
KeyData *pTuple;
pTab = pRes->pTable;
iTable = pTab->tnum;
pWhere = pRes->pWhere;
pIdList = pRes->pIdList;
/*
** open the base table with iCur=0
*/
iCur = base = *nCur;
rc = eDbBtreeCursor(db->pBt,iTable,1,&db->pCur[iCur++]);
if( rc ) {
goto err_handle;
}
/*
** open the index
*/
pIdx = pTab->pIndex;
for(; pIdx; pIdx=pIdx->pNext){
rc = eDbBtreeCursor(db->pBt,pIdx->tnum,1,&db->pCur[iCur++]);
if( rc ) goto err_handle;
}
if(!pWhere){
/*
** update all record
*/
}else{
int ok;
int zOldKey,zNewKey;
if(aCExpr.useIndex){
}else{
rc = eDbBtreeFirst(db->pCur[base],&res);
while(!rc && !res){
/*exec each expression*/
ok = checkConditionOk(db,base,&aCExpr);
if( ok ){
int i;
pIdx = pTab->pIndex;
/*
** update the record in table
*/
eDbBtreeKey(db->pCur[base],0,SIZEOFINT,(char *)&zOldKey);
pTuple = makeOneTupleRec(db->pCur[base],zOldKey,TK_UPDATE,pRes);
if(pTab->hasPrimKey && pTab->iPKey >= 0){
/*
** integer primary key must be unique
*/
memcpy(&zNewKey,pTuple->pKey,SIZEOFINT);
if(zNewKey != zOldKey){
rc = eDbBtreeDelete(db->pCur[base]);
rc = eDbBtreeMoveto(db->pCur[base],pTuple->pKey,pTuple->nKey,&res);
if( res == 0) goto err_handle;
}
}
/*
** update index
*/
for(i=1; pIdx; pIdx=pIdx->pNext, i++){
rc = updateIndexRec(db,pIdx,pRes,zOldKey,i,base);
if( rc ) goto err_handle;
}
rc = eDbBtreeInsert(db->pCur[base],pTuple->pKey,pTuple->nKey,pTuple->pData,pTuple->nData);
eDbFreeKayData(pTuple);
nRec ++;
}
rc = eDbBtreeNext(db->pCur[base],&res);
} /* end while */
}
}
nRec = nRec;
err_handle:
*nCur = iCur;
return rc;
}
int dmleDbDelete(eDb *db,ParseResult *pRes, int *nCur){
int rc,res;
int iTable;
int iCur;
int base;
int aiCur[MAX_CURSORS];
int nRec = 0;
Table *pTab;
Index *pIdx;
Expr *pExpr;
pTab = pRes->pTable;
iTable = pTab->tnum;
pExpr = pRes->pWhere;
memset(aiCur,-1,sizeof(aiCur));
iCur = base = *nCur;
/* open the base table with iCur=0*/
rc = eDbBtreeCursor(db->pBt,iTable,1,&db->pCur[iCur++]);
if( rc ){
goto err_handle;
}
pIdx = pTab->pIndex;
/*
** open all index
*/
for(;pIdx;pIdx=pIdx->pNext){
rc = eDbBtreeCursor(db->pBt,pIdx->tnum,1,&db->pCur[iCur++]);
if( rc ) goto err_handle;
}
if(!pExpr){/*delete all record*/
}else{
int ok;
if(aCExpr.useIndex){
}else{
rc = eDbBtreeFirst(db->pCur[base],&res);
while(!rc && !res){
ok = checkConditionOk(db,base,&aCExpr);
if( ok ){
int n,m,k,zKey;
char zCols[MAXLEN_IDXCOLUMN];
char idxKey[MAXLEN_IDXKEY];
eDbBtreeKey(db->pCur[base],0,SIZEOFINT,(char*)&zKey);
pIdx = pTab->pIndex;
for(k=base+1;pIdx;pIdx=pIdx->pNext,k++){
rc = eDbBtreeCursor(db->pBt,pIdx->tnum,1,&db->pCur[k]);
if( rc ){
goto err_handle;
}
/*
** make idx key
*/
idxKey[0] = 0;
for(n=0;n<pIdx->nColumn;n++){
m = pIdx->aiColumn[n];
eDbBtreeGetColumnData(db->pCur[base],m,zCols);
strcat(idxKey,zCols);
}
m = strlen(idxKey);
idxKey[m++] = 0;
memcpy(&idxKey[m],&zKey,SIZEOFINT);
m += SIZEOFINT;
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -