📄 exec.c
字号:
** search the record with the idxKey
*/
rc = eDbBtreeMoveto(db->pCur[k],idxKey,m,&res);
if(res == 0){
eDbBtreeDelete(db->pCur[k]);
}
}
rc = eDbBtreeDelete(db->pCur[base]);
nRec ++;
}
rc = eDbBtreeNext(db->pCur[base],&res);
}
}
}
nRec = nRec;
err_handle:
*nCur = iCur;
return rc;
}
int dmleDbSelect(eDb *db,ParseResult *pRes, int *nCur){
int rc,res;
int iCur;
int base;
int aiCols[MAXLEN_COLUMN]; /* the field-th in table of result set*/
int nColumn;
int aiCur[MAXLEN_COLUMN];
int nTab;
int nRec = 0;
SrcList *pSrc;
Expr *pWhere;
ExprList *pColList;
pWhere = pRes->pSelect->pWhere;
pSrc = pRes->pSelect->pSrc;
pColList = pRes->pSelect->pEList;
nTab = pSrc->nSrc;
iCur = base = *nCur;
if( pColList ){
int i;
Expr *pExpr;
for( i=0; i<pColList->nExpr; i++){
pExpr = pColList->a[i].pExpr;
aiCols[i] = pExpr->iColumn;
aiCur[i] = pExpr->iTable;
}
nColumn = i;
}
/* open the base table with iCur*/
if(openTables(db,pSrc,&iCur) > 0)
goto err_handle;
if(!pWhere){
/*
** do natural join
*/
int p1Cur,p2Cur,p3Cur;
Table *pTab1,*pTab2,*pTab3;
pTab1 = pTab2 = pTab3 = 0;
if(pSrc->nSrc > 0) {
pTab1 = pSrc->a[0].pTab;
p1Cur = base + pSrc->a[0].iCursor;
}
if(pSrc->nSrc > 1) {
pTab2 = pSrc->a[1].pTab;
p2Cur = base + pSrc->a[1].iCursor;
}
if(pSrc->nSrc > 2) {
pTab3 = pSrc->a[2].pTab;
p3Cur = base + pSrc->a[2].iCursor;
}
/*
** select *|collist from tbl_name1,tbl_name2,tble_name3
** pColList is the column list
*/
if( pTab1 ){
rc = eDbBtreeFirst(db->pCur[p1Cur],&res);
}
for(;pTab1;){
if( pTab2 ){
rc = eDbBtreeFirst(db->pCur[p2Cur],&res);
}
for(;pTab2;){
if( pTab3 ){
rc = eDbBtreeFirst(db->pCur[p3Cur],&res);
}
for(;pTab3;){
nRec = dispRecord(db,aiCols,aiCur,nColumn,base,nRec);
rc = eDbBtreeNext(db->pCur[p3Cur],&res);
if(rc || res) break;
}/* for(;;) pTab3 */
if(pTab3 == 0){
nRec = dispRecord(db,aiCols,aiCur,nColumn,base,nRec);
}
rc = eDbBtreeNext(db->pCur[p2Cur],&res);
if(rc || res) break;
}/*for(;;) pTab2*/
if(pTab2 == 0){
nRec = dispRecord(db,aiCols,aiCur,nColumn,base,nRec);
}
rc = eDbBtreeNext(db->pCur[p1Cur],&res);
if(rc || res) break;
}/* for(;;) pTab3 */
}else{
int ok;
if(aCExpr.useIndex){
/*open the index */
rc = openIndex(db, &iCur);
}else{
int p1Cur,p2Cur,p3Cur;
Table *pTab1,*pTab2,*pTab3;
pTab1 = pTab2 = pTab3 = 0;
if(pSrc->nSrc > 0) {
pTab1 = pSrc->a[0].pTab;
p1Cur = base + pSrc->a[0].iCursor;
}
if(pSrc->nSrc > 1) {
pTab2 = pSrc->a[1].pTab;
p2Cur = base + pSrc->a[1].iCursor;
}
if(pSrc->nSrc > 2) {
pTab3 = pSrc->a[2].pTab;
p3Cur = base + pSrc->a[2].iCursor;
}
/*
** select *|collist from tbl_name1,tbl_name2,tble_name3
** pColList is the column list
*/
if( pTab1 ){
rc = eDbBtreeFirst(db->pCur[p1Cur],&res);
}
for(;pTab1;){
if( pTab2 ){
rc = eDbBtreeFirst(db->pCur[p2Cur],&res);
}
for(;pTab2;){
if( pTab3 ){
rc = eDbBtreeFirst(db->pCur[p3Cur],&res);
}
for(;pTab3;){
ok = checkConditionOk(db,base,&aCExpr);
if( ok ){
nRec = dispRecord(db,aiCols,aiCur,nColumn,base,nRec);
}
rc = eDbBtreeNext(db->pCur[p3Cur],&res);
if(rc || res) break;
}/*for(;;)*/
if(pTab3 == 0){
ok = checkConditionOk(db,base,&aCExpr);
if( ok ){
nRec = dispRecord(db,aiCols,aiCur,nColumn,base,nRec);
}
}
rc = eDbBtreeNext(db->pCur[p2Cur],&res);
if(rc || res) break;
}/*for(;;)*/
if(pTab2 == 0){
ok = checkConditionOk(db,base,&aCExpr);
if( ok ){
nRec = dispRecord(db,aiCols,aiCur,nColumn,base,nRec);
}
}
rc = eDbBtreeNext(db->pCur[p1Cur],&res);
if(rc || res) break;
}/*for(;;)*/
}
}
nRec = nRec;
err_handle:
*nCur = iCur;
return rc;
}
KeyData *fillKeyData(int zKey, char *apCols[], int nCol){
char *pBuf;
int nByte;
int nPointer;
int idxWidth;
int iLen[MAX_COLUMNS];
int i,j,offset;
KeyData *pTuple = eDbMalloc(sizeof(KeyData));
pTuple->nKey = sizeof(int);
pTuple->pKey = eDbMalloc(sizeof(int));
memcpy(pTuple->pKey,(const char *)&zKey,sizeof(int));
nByte = 0;
for(i=0; i<nCol; i++){
if(apCols[i]){
iLen[i] = strlen(apCols[i])+1;
}
else{
iLen[i] = 0;
}
nByte += iLen[i];
}
nPointer = nCol + 1;
if( nByte + nPointer < 256 ){
idxWidth = 1;
}else if( nByte + 2*nPointer < 65536 ){
idxWidth = 2;
}else{
idxWidth = 3;
}
offset = idxWidth*nPointer;
nByte += offset;
pBuf = pTuple->pData = eDbMalloc(nByte);
pTuple->nData = nByte;
/* ------------------------------------------------------------
** p1 | p2 | p3 | pn | d1 | d2 | d3 |...| dn | d(n+1)
** ------------------------------------------------------------
** |____|____|____|____| | |
** |____|____|_________| |
** |____|______________|
** |______________________|
*/
/* store the pointer p1, p2 ...*/
j = 0;
for(i=0;i<nPointer;i++){
pBuf[j++] = offset & 0xff;
if(idxWidth > 1){
pBuf[j++] = (offset >> 8) & 0xff;
}
if(idxWidth > 2){
pBuf[j++] = (offset >> 16) & 0xff;
}
offset += iLen[i];
}
/* store the column value d1, d2 ...*/
for(i=0; i<nCol; i++){
if(apCols[i]){
strcpy(&pBuf[j],apCols[i]);
}
j += iLen[i];
}
return pTuple;
}
/*
** update index record
** pIdx point to a index
** iCur is the opened index cursor
** tCur is the opened base table cursor
** return 0 if success, return 1 if any error
*/
int updateIndexRec(eDb *db,Index *pIdx,ParseResult *pRes,
int zKey, int iCur,int tCur){
int i,k;
int rc,res;
char zCols[MAXLEN_IDXCOLUMN];
char zIdxKey[MAXLEN_IDXKEY];
KeyData *p;
zIdxKey[0] = 0;
p = makeIdxKey(db->pCur[tCur],pIdx,zKey,TK_UPDATE,pRes);
if( p == 0) return 0;
/*
** make a old index key
*/
for(i=0;i<pIdx->nColumn;i++){
k = pIdx->aiColumn[i];
eDbBtreeGetColumnData(db->pCur[tCur],k,zCols);
strcat(zIdxKey,zCols);
}
k = strlen(zIdxKey);
zIdxKey[k++] = 0;
memcpy(&zIdxKey[k],&zKey,SIZEOFINT);
k += SIZEOFINT;
/*
** find the old index record
*/
rc = eDbBtreeMoveto(db->pCur[iCur],zIdxKey,k,&res);
assert(res == 0);
if(res == 0) {
/*
** delete the old key
*/
res = 1;
rc = eDbBtreeDelete(db->pCur[iCur]);
if( pIdx->unique ){
rc = eDbBtreeMoveto(db->pCur[iCur],
p->pKey,p->nKey-SIZEOFINT,&res);
if(res >= 0){
rc = eDbBtreeKeyCompare(db->pCur[iCur],
p->pKey,p->nKey-SIZEOFINT,SIZEOFINT,&res);
}
}
if(res){
rc = eDbBtreeInsert(db->pCur[iCur],
p->pKey,p->nKey,0,0);
eDbFreeKayData(p);
}
}
return res == 0;
}
int eDb_exec(eDb *db,const char *zSql){
int rc;
int nCur;
int i;
char *errMsg;
Parser sParse;
ParseResult *pRes;
eDbBtreeBeginTrans(db->pBt);
nCur = 0;
memset(&sParse,0,sizeof(sParse));
sParse.db = db;
rc = eDbRunParser(&sParse,zSql,&errMsg);
pRes = sParse.pResult;
if( rc || sParse.rc ){
goto rollback;
}
if(pRes == 0) goto rollback;
pRes->zSql=eDbStrDup(zSql);
switch(pRes->op){
case Op_CreateTable:{
rc = ddlCreateTable(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_DropTable:{
rc = ddlDropTable(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_CreateIndex:{
rc = ddlCreateIndex(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_DropIndex:{
rc = ddlDropIndex(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_Insert:{
rc = dmleDbInsert(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_Update:{
rc = dmleDbUpdate(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_Delete:{
rc = dmleDbDelete(db,pRes,&nCur);
if( rc ) goto rollback;
break;
}
case Op_Select:{
rc = dmleDbSelect(db,pRes,&nCur);
break;
}
default:{
}
}
if(nCur > 4){
for(i=0; i< nCur; i++){
eDbBtreeCloseCursor(db->pCur[i]);
}
nCur = 0;
}
eDbFreeParseResult(pRes);
rc = eDbBtreeCommit(db->pBt);
if( rc ){
goto rollback;
}
for(i=0; i< nCur; i++){
eDbBtreeCloseCursor(db->pCur[i]);
}
return eDb_OK;
rollback:
eDbBtreeRollback(db->pBt);
for(i=0; i< nCur; i++){
eDbBtreeCloseCursor(db->pCur[i]);
}
eDbFreeParseResult(pRes);
return eDb_ERROR;
}
int checkConditionOk(eDb *db, int base, WhereExpr *pW){
int i;
int rc,res;
int allExprIsEnd;
int oldOp,iCol;
int iCur;
int type;
int allExprOk,singleExprOk;
CExpr *pCE;
Expr *pE,*pLeft,*pRight;
char *zDes,*zSrc;
for(i=0;i<pW->nExpr;){
allExprIsEnd = 0;
pE = pW->a[i].pExpr;
pCE = &pW->a[i];
pLeft = pE->pLeft;
pRight = pE->pRight;
assert(pLeft !=0 && pRight != 0);
type = pLeft->dataType;
if(pRight->op != TK_COLUMN){
zDes = eDbStrNDup(pRight->token.z,pRight->token.n);
}else{
iCol = pRight->iColumn;
iCur = base + pRight->iTable;
zDes = eDbBtreeGetColumnData(db->pCur[iCur],iCol,0);
}
eDbDequote(zDes);
iCol = pLeft->iColumn;
iCur = base + pLeft->iTable;
if(i == 0) oldOp = 0;
else
oldOp = pW->a[i-1].op;
/*loop search from table*/
rc = res = 0;
singleExprOk = 0;
zSrc = eDbBtreeGetColumnData(db->pCur[iCur],iCol,0);
if(eDbStrCompareOK(pE->op,type,zSrc,zDes)){
singleExprOk = 1;
}
eDbFree(zSrc);
eDbFree(zDes);
switch(oldOp){
case TK_AND:{
allExprOk &= singleExprOk;
break;
}
case TK_OR:{
allExprOk |= singleExprOk;
break;
}
default:{
allExprOk = singleExprOk;
}
}
switch(pCE->op){
case TK_AND:{
if(singleExprOk) i = pCE->next;
else{
i = pCE->go;
while(i > 0 && pW->a[i-1].op == TK_AND){
i = pW->a[i].go;
}
}
break;
}
case TK_OR:{
if(!singleExprOk) i = pCE->next;
else{
i = pCE->go;
while(i > 0 && pW->a[i-1].op == TK_OR){
i = pW->a[i].go;
}
}
break;
}
default:{
allExprIsEnd = 1;
}
}
if(i >= pW->nExpr || allExprIsEnd || i==0 ){
break;
}
}/* end for(i=0;i<aCExpr.nExpr;i++)*/
return allExprOk;
}
int dispRecord(eDb *db, int aiCols[],int aiCur[], int n, int base, int nRec){
int i,j;
char *zBuf;
fprintf(fout,"\nRecord%d:\t",nRec+1);
for(i=0;i<n;i++){
j = aiCur[i];
zBuf = eDbBtreeGetColumnData(db->pCur[base+j],aiCols[i],0);
fprintf(fout,"%s | ",zBuf);
eDbFree(zBuf);
}
nRec ++;
return nRec;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -