void ParseComment (FILE* file,char type,Comment* doc){ char* line=NULL; StringList bloc=NULL; int end=0; if(doc==NULL)doc=newComment(); if(doc==NULL)exit(EXIT_FAILURE); switch(type){ case '/': line=GetLine(file); ParseLine(file,doc); free(line); break; case '*': bloc=newStringList(); while(end==0){ char* tmp=GetLine(file); int length=strlen(tmp); if(strstr(tmp,"*/")!=NULL)end=1; addtoStringList(bloc,tmp); } StringCell* tmp; int i; for(tmp=bloc.first, i=1;i<=bloc.size;i++, tmp=tmp->suivant){ ParseLine(tmp->string,doc); } freeStringList(bloc); break; default: break; } }
/** \brief Funcion para crear un nuevo comentario * \param listaUsuarios: arraylist donde se guardan los usuarios * \param listaComentarios: arraylist donde se guardan los comentarios */ void nuevoComentario(ArrayList *listaUsuarios,ArrayList *listaComentarios) { char nickAux[51]; char passAux[51]; char commentAux[250]; User *usuario; EComments *comentario; int i,id; printf("Ingrese su nick: "); gets(nickAux); fflush(stdin); printf("Ingrese su pass: "******"Ingrese su comentario: "); gets(commentAux); fflush(stdin); id=listaComentarios->size; comentario=newComment(commentAux, usuario->id,id); if(listaComentarios->size > 0) listaComentarios->push(listaComentarios,0,comentario); else listaComentarios->add(listaComentarios,comentario); } } }
short SlkToken::get(void) { if (NULL == mSource || NULL == mErrorAndStringBuffer) { return END_OF_SLK_INPUT_; } for (;;) { if (*mIterator == '\0') { if (isCanFinish()) { newToken(); endTokenWithEof(); return END_OF_SLK_INPUT_; } else { if (!mIterator.Load()) { newToken(); endTokenWithEof(); return END_OF_SLK_INPUT_; } } } int isSkip = TRUE; //跳过注释与白空格 for (; isSkip && *mIterator != '\0';) { isSkip = FALSE; for (; isWhiteSpace(*mIterator); ++mIterator) { if (*mIterator == '\n') { ++mLineNumber; if (mCommentNum <= 0) { mCommentOnNewLine = TRUE; } } isSkip = TRUE; } //#引导的单行注释 if (*mIterator == '#') { newComment(); for (; *mIterator != '\0' && *mIterator != '\n'; ++mIterator) { if (*mIterator != '\r') pushCommentChar(*mIterator); } endComment(); isSkip = TRUE; } //C++风格的单行注释与多行注释 if (*mIterator == '/' && (*(mIterator + 1) == '/' || *(mIterator + 1) == '*')) { newComment(); pushCommentChar(*mIterator); ++mIterator; if (*mIterator == '/') { pushCommentChar(*mIterator); ++mIterator; for (; *mIterator != '\0' && *mIterator != '\n'; ++mIterator) { if (*mIterator != '\r') pushCommentChar(*mIterator); } isSkip = TRUE; } else if (*mIterator == '*') { pushCommentChar(*mIterator); ++mIterator; for (;;) { if (*mIterator != '\0') { if (*mIterator == '\n') { pushCommentChar(*mIterator); ++mLineNumber; } else if (*mIterator == '*' && *(mIterator + 1) == '/') { pushCommentChar(*mIterator); ++mIterator; pushCommentChar(*mIterator); ++mIterator; break; } else if (*mIterator != '\r') { pushCommentChar(*mIterator); } } else { if (mIterator.Load()) { continue; } else { endComment(); newToken(); endTokenWithEof(); return END_OF_SLK_INPUT_; } } ++mIterator; } isSkip = TRUE; } endComment(); } } if (*mIterator != '\0') break; } newToken(); if (isCanFinish()) setCanFinish(FALSE); if (*mIterator == '{' && *(mIterator + 1) == ':') { ++mIterator; ++mIterator; int line = mLineNumber; //搜索脚本结束 :} for (; *mIterator != '\0';) { while (*mIterator != '\0' && *mIterator != ':') { if (*mIterator == '\n')++mLineNumber; pushTokenChar(*mIterator); ++mIterator; } if (*mIterator == '\0') break; IScriptSource::Iterator next = mIterator + 1; if (*next == '}') { ++mIterator; ++mIterator; break; } else { pushTokenChar(*mIterator); ++mIterator; } } if (*mIterator == '\0') { char* pInfo = mErrorAndStringBuffer->NewErrorInfo(); if (pInfo) tsnprintf(pInfo, MAX_ERROR_INFO_CAPACITY, "[line %d ]:ExternScript can't finish!", line); } endToken(); if (myhavelinefeed(mCurToken)){ removeFirstAndLastEmptyLine(); } return SCRIPT_CONTENT_; } else if (isOperator(*mIterator)) {//操作符 getOperatorToken(); return getOperatorTokenValue(); } else if (*mIterator == '.' && 0 == myisdigit(*(mIterator + 1), FALSE)) { char c = *mIterator; ++mIterator; pushTokenChar(c); endToken(); return DOT_; } else if (*mIterator == '(') { ++mIterator; pushTokenChar('('); endToken(); return LPAREN_; } else if (*mIterator == ')') { ++mIterator; pushTokenChar(')'); endToken(); return RPAREN_; } else if (*mIterator == '[') { ++mIterator; pushTokenChar('['); endToken(); return LBRACK_; } else if (*mIterator == ']') { ++mIterator; pushTokenChar(']'); endToken(); return RBRACK_; } else if (*mIterator == '{') { ++mIterator; pushTokenChar('{'); endToken(); return LBRACE_; } else if (*mIterator == '}') { ++mIterator; pushTokenChar('}'); endToken(); return RBRACE_; } else if (*mIterator == ',') { ++mIterator; pushTokenChar(','); endToken(); return COMMA_; } else if (*mIterator == ';') { ++mIterator; pushTokenChar(';'); endToken(); return SEMI_; } else {//关键字、标识符或常数 if (*mIterator == '"' || *mIterator == '\'') {//引号括起来的名称或关键字 int line = mLineNumber; char c = *mIterator; for (++mIterator; *mIterator != '\0' && *mIterator != c;) { if (*mIterator == '\n')++mLineNumber; if (*mIterator == '\\') { //pushTokenChar(*mIterator); ++mIterator; } pushTokenChar(*mIterator); ++mIterator; if (*mIterator == '\0') { if (mIterator.Load()) { continue; } else { char* pInfo = mErrorAndStringBuffer->NewErrorInfo(); if (pInfo) tsnprintf(pInfo, MAX_ERROR_INFO_CAPACITY, "[line %d ]:String can't finish!", line); endTokenWithEof(); return END_OF_SLK_INPUT_; } } } if (*mIterator != '\0') { ++mIterator; } else { char* pInfo = mErrorAndStringBuffer->NewErrorInfo(); if (pInfo) tsnprintf(pInfo, MAX_ERROR_INFO_CAPACITY, "[line %d ]:String can't finish!", line); } endToken(); if (myhavelinefeed(mCurToken)){ removeFirstAndLastEmptyLine(); } return STRING_; } else { int isNum = TRUE; int isHex = FALSE; if (*mIterator == '0' && *(mIterator + 1) == 'x') { isHex = TRUE; pushTokenChar(*mIterator); ++mIterator; pushTokenChar(*mIterator); ++mIterator; } for (; !isSpecialChar(*mIterator); ++mIterator) { if (*mIterator == '#') break; else if (*mIterator == '/') { IScriptSource::Iterator next = mIterator + 1; if (*next != '\0' && (*next == '/' || *next == '*')) { break; } } else if (*mIterator == '.') { if (!isNum) { break; } else { IScriptSource::Iterator next = mIterator + 1; if (0 == myisdigit(*next, isHex)) { break; } } } else if (0 == myisdigit(*mIterator, isHex)) { isNum = FALSE; } pushTokenChar(*mIterator); } endToken(); if (isNum) { return NUMBER_; } else { int token = handleStringOrScriptDelimiter(); if (token) return token; return IDENTIFIER_; } } } }
str OPTevaluateImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { InstrPtr p; int i, k, limit, *alias = 0, barrier; MalStkPtr env = NULL; int profiler; int debugstate = cntxt->itrace, actions = 0, constantblock = 0; int *assigned = 0, use; char buf[256]; lng usec = GDKusec(); str msg = MAL_SUCCEED; (void)stk; (void)pci; if ( mb->inlineProp ) return MAL_SUCCEED; cntxt->itrace = 0; #ifdef DEBUG_OPT_EVALUATE fprintf(stderr, "Constant expression optimizer started\n"); #endif assigned = (int*) GDKzalloc(sizeof(int) * mb->vtop); if (assigned == NULL) throw(MAL,"optimzier.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL); alias = (int*)GDKzalloc(mb->vsize * sizeof(int) * 2); /* we introduce more */ if (alias == NULL){ GDKfree(assigned); throw(MAL,"optimzier.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL); } // arguments are implicitly assigned by context p = getInstrPtr(mb, 0); for ( k =p->retc; k < p->argc; k++) assigned[getArg(p,k)]++; limit = mb->stop; for (i = 1; i < limit; i++) { p = getInstrPtr(mb, i); // The double count emerging from a barrier exit is ignored. if (! blockExit(p) || (blockExit(p) && p->retc != p->argc)) for ( k =0; k < p->retc; k++) if ( p->retc != p->argc || p->token != ASSIGNsymbol ) assigned[getArg(p,k)]++; } for (i = 1; i < limit && cntxt->mode != FINISHCLIENT; i++) { p = getInstrPtr(mb, i); // to avoid management of duplicate assignments over multiple blocks // we limit ourselves to evaluation of the first assignment only. use = assigned[getArg(p,0)] == 1 && !(p->argc == p->retc && blockExit(p)); for (k = p->retc; k < p->argc; k++) if (alias[getArg(p, k)]) getArg(p, k) = alias[getArg(p, k)]; #ifdef DEBUG_OPT_EVALUATE fprintInstruction(stderr , mb, 0, p, LIST_MAL_ALL); #endif /* be aware that you only assign once to a variable */ if (use && p->retc == 1 && OPTallConstant(cntxt, mb, p) && !isUnsafeFunction(p)) { barrier = p->barrier; p->barrier = 0; profiler = malProfileMode; /* we don't trace it */ malProfileMode = 0; if ( env == NULL) { env = prepareMALstack(mb, 2 * mb->vsize); if (!env) { msg = createException(MAL,"optimizer.evaluate", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } env->keepAlive = TRUE; } msg = reenterMAL(cntxt, mb, i, i + 1, env); malProfileMode= profiler; p->barrier = barrier; #ifdef DEBUG_OPT_EVALUATE fprintf(stderr, "#retc var %s\n", getVarName(mb, getArg(p, 0))); fprintf(stderr, "#result:%s\n", msg == MAL_SUCCEED ? "ok" : msg); #endif if (msg == MAL_SUCCEED) { int nvar; ValRecord cst; actions++; cst.vtype = 0; VALcopy(&cst, &env->stk[getArg(p, 0)]); /* You may not overwrite constants. They may be used by * other instructions */ nvar = getArg(p, 1) = defConstant(mb, getArgType(mb, p, 0), &cst); if (nvar >= env->stktop) { VALcopy(&env->stk[getArg(p, 1)], &getVarConstant(mb, getArg(p, 1))); env->stktop = getArg(p, 1) + 1; } alias[getArg(p, 0)] = getArg(p, 1); p->argc = 2; p->token = ASSIGNsymbol; clrFunction(p); p->barrier = barrier; /* freeze the type */ setVarFixed(mb,getArg(p,1)); setVarUDFtype(mb,getArg(p,1)); #ifdef DEBUG_OPT_EVALUATE {str tpename; fprintf(stderr, "Evaluated new constant=%d -> %d:%s\n", getArg(p, 0), getArg(p, 1), tpename = getTypeName(getArgType(mb, p, 1))); GDKfree(tpename); } #endif } else { /* if there is an error, we should postpone message handling, as the actual error (eg. division by zero ) may not happen) */ #ifdef DEBUG_OPT_EVALUATE fprintf(stderr, "Evaluated %s\n", msg); #endif freeException(msg); msg= MAL_SUCCEED; mb->errors = 0; } } constantblock += blockStart(p) && OPTallConstant(cntxt, mb, p); /* default */ } // produces errors in SQL when enabled if ( constantblock) msg = OPTremoveUnusedBlocks(cntxt, mb); cntxt->itrace = debugstate; /* Defense line against incorrect plans */ /* Plan is unaffected */ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","evaluate",actions,usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); wrapup: if ( env) freeStack(env); if(assigned) GDKfree(assigned); if(alias) GDKfree(alias); return msg; }
CommentNode* BaseCompiler::addComment(const char* str) { CommentNode* node = newComment(str); if (node == NULL) return NULL; return static_cast<CommentNode*>(addNode(node)); }
str OPTvolcanoImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, limit; int mvcvar = -1; int count=0; InstrPtr p,q, *old = mb->stmt; char buf[256]; lng usec = GDKusec(); str msg = MAL_SUCCEED; (void) pci; (void) cntxt; (void) stk; /* to fool compilers */ if ( mb->inlineProp ) return MAL_SUCCEED; limit= mb->stop; if ( newMalBlkStmt(mb, mb->ssize + 20) < 0) throw(MAL,"optimizer.volcano", SQLSTATE(HY001) MAL_MALLOC_FAIL); for (i = 0; i < limit; i++) { p = old[i]; pushInstruction(mb,p); if( getModuleId(p) == sqlRef && getFunctionId(p)== mvcRef ){ mvcvar = getArg(p,0); continue; } if( count < MAXdelays && getModuleId(p) == algebraRef ){ if( getFunctionId(p) == selectRef || getFunctionId(p) == thetaselectRef || getFunctionId(p) == likeselectRef || getFunctionId(p) == joinRef ){ q= newInstruction(0,languageRef,blockRef); setDestVar(q, newTmpVariable(mb,TYPE_any)); q = pushArgument(mb,q,mvcvar); q = pushArgument(mb,q,getArg(p,0)); mvcvar= getArg(q,0); pushInstruction(mb,q); count++; } continue; } if( count < MAXdelays && getModuleId(p) == groupRef ){ if( getFunctionId(p) == subgroupdoneRef || getFunctionId(p) == groupdoneRef ){ q= newInstruction(0,languageRef,blockRef); setDestVar(q, newTmpVariable(mb,TYPE_any)); q = pushArgument(mb,q,mvcvar); q = pushArgument(mb,q,getArg(p,0)); mvcvar= getArg(q,0); pushInstruction(mb,q); count++; } } if( getModuleId(p) == sqlRef){ if ( getFunctionId(p) == bindRef || getFunctionId(p) == bindidxRef || getFunctionId(p)== tidRef || getFunctionId(p)== appendRef || getFunctionId(p)== updateRef || getFunctionId(p)== deleteRef ){ setArg(p,p->retc,mvcvar); } } } GDKfree(old); /* Defense line against incorrect plans */ if( count){ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); } /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","volcano",count,usec); newComment(mb,buf); if( count >= 0) addtoMalBlkHistory(mb); return msg; }
str OPTmultiplexImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { InstrPtr *old = 0, p; int i, limit, slimit, actions= 0; str msg= MAL_SUCCEED; char buf[256]; lng usec = GDKusec(); (void) stk; (void) pci; old = mb->stmt; limit = mb->stop; slimit = mb->ssize; if ( newMalBlkStmt(mb, mb->ssize) < 0 ) throw(MAL,"optimizer.mergetable", SQLSTATE(HY001) MAL_MALLOC_FAIL); for (i = 0; i < limit; i++) { p = old[i]; if (msg == MAL_SUCCEED && isMultiplex(p)) { if ( MANIFOLDtypecheck(cntxt,mb,p,0) != NULL){ setFunctionId(p, manifoldRef); p->typechk = TYPE_UNKNOWN; pushInstruction(mb, p); actions++; continue; } msg = OPTexpandMultiplex(cntxt, mb, stk, p); if( msg== MAL_SUCCEED){ freeInstruction(p); old[i]=0; actions++; continue; } pushInstruction(mb, p); actions++; } else if( old[i]) pushInstruction(mb, p); } for(;i<slimit; i++) if( old[i]) freeInstruction(old[i]); GDKfree(old); /* Defense line against incorrect plans */ if( msg == MAL_SUCCEED && actions > 0){ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); } /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","multiplex",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return msg; }
str OPTjsonImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, j, limit, slimit; int bu = 0, br = 0, bj = 0; str nme; InstrPtr p,q; int actions = 0; InstrPtr *old; char buf[256]; lng usec = GDKusec(); str msg = MAL_SUCCEED; (void) pci; (void) cntxt; (void) stk; /* to fool compilers */ old= mb->stmt; limit= mb->stop; slimit = mb->ssize; if ( newMalBlkStmt(mb,mb->stop) < 0) throw(MAL,"optimizer.json", SQLSTATE(HY001) MAL_MALLOC_FAIL); for (i = 0; i < limit; i++) { p = old[i]; if( getModuleId(p) == sqlRef && getFunctionId(p) == affectedRowsRef) { q = newInstruction(0, jsonRef, resultSetRef); q = pushArgument(mb, q, bu); q = pushArgument(mb, q, br); q = pushArgument(mb, q, bj); j = getArg(q,0); p= getInstrPtr(mb,0); setDestVar(q, newTmpVariable(mb, TYPE_str)); pushInstruction(mb,p); q = newInstruction(0, NULL, NULL); q->barrier = RETURNsymbol; getArg(q,0)= getArg(p,0); pushArgument(mb,q,j); pushInstruction(mb,q); actions++; continue; } if( getModuleId(p) == sqlRef && getFunctionId(p) == rsColumnRef) { nme = getVarConstant(mb,getArg(p,4)).val.sval; if (strcmp(nme,"uuid")==0) bu = getArg(p,7); if (strcmp(nme,"lng")==0) br = getArg(p,7); if (strcmp(nme,"json")==0) bj = getArg(p,7); freeInstruction(p); actions++; continue; } pushInstruction(mb,p); } for(; i<slimit; i++) if (old[i]) freeInstruction(old[i]); GDKfree(old); /* Defense line against incorrect plans */ if( actions > 0){ chkTypes(cntxt->usermodule, mb, FALSE); chkFlow(mb); chkDeclarations(mb); } /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","json",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return msg; }
str OPTgeneratorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { InstrPtr p,q, *old, *series; int i, k, limit, slimit, actions=0; str m; str bteRef = getName("bte"); str shtRef = getName("sht"); str intRef = getName("int"); str lngRef = getName("lng"); str fltRef = getName("flt"); str dblRef = getName("dbl"); char buf[256]; lng usec= GDKusec(); (void) cntxt; (void) stk; (void) pci; series = (InstrPtr*) GDKzalloc(sizeof(InstrPtr) * mb->vtop); if(series == NULL) throw(MAL,"optimizer.generator", SQLSTATE(HY001) MAL_MALLOC_FAIL); old = mb->stmt; limit = mb->stop; slimit = mb->ssize; // check applicability first for( i=0; i < limit; i++){ p = old[i]; if ( getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef) break; } if (i == limit) { GDKfree(series); return 0; } if (newMalBlkStmt(mb, mb->ssize) < 0) { GDKfree(series); throw(MAL,"optimizer.generator", SQLSTATE(HY001) MAL_MALLOC_FAIL); } for( i=0; i < limit; i++){ p = old[i]; if (p->token == ENDsymbol){ pushInstruction(mb,p); break; } if ( getModuleId(p) == generatorRef && getFunctionId(p) == seriesRef){ series[getArg(p,0)] = p; setModuleId(p, generatorRef); setFunctionId(p, parametersRef); typeChecker(cntxt->usermodule, mb, p, TRUE); pushInstruction(mb,p); } else if ( getModuleId(p) == algebraRef && getFunctionId(p) == selectRef && series[getArg(p,1)]){ errorCheck(p,algebraRef,getArg(p,1)); } else if ( getModuleId(p) == algebraRef && getFunctionId(p) == thetaselectRef && series[getArg(p,1)]){ errorCheck(p,algebraRef,getArg(p,1)); } else if ( getModuleId(p) == algebraRef && getFunctionId(p) == projectionRef && series[getArg(p,2)]){ errorCheck(p,algebraRef,getArg(p,2)); } else if ( getModuleId(p) == sqlRef && getFunctionId(p) == putName("exportValue") && isaBatType(getArgType(mb,p,0)) ){ // interface expects scalar type only, not expressable in MAL signature mb->errors=createException(MAL, "generate_series", SQLSTATE(42000) "internal error, generate_series is a table producing function"); }else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == bteRef && series[getArg(p,1)] && p->argc == 2 ){ casting(bte); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == shtRef && series[getArg(p,1)] && p->argc == 2 ){ casting(sht); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == intRef && series[getArg(p,1)] && p->argc == 2 ){ casting(int); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == lngRef && series[getArg(p,1)] && p->argc == 2 ){ casting(lng); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == fltRef && series[getArg(p,1)] && p->argc == 2 ){ casting(flt); } else if ( getModuleId(p) == batcalcRef && getFunctionId(p) == dblRef && series[getArg(p,1)] && p->argc == 2 ){ casting(dbl); } else if ( getModuleId(p) == languageRef && getFunctionId(p) == passRef ) pushInstruction(mb,p); else { // check for use without conversion for(k = p->retc; k < p->argc; k++) if( series[getArg(p,k)]){ m = getModuleId(p); setModuleId(p, generatorRef); typeChecker(cntxt->usermodule, mb, p, TRUE); if(p->typechk == TYPE_UNKNOWN){ setModuleId(p,m); typeChecker(cntxt->usermodule, mb, p, TRUE); setModuleId(series[getArg(p,k)], generatorRef); setFunctionId(series[getArg(p,k)], seriesRef); typeChecker(cntxt->usermodule, mb, series[getArg(p,k)], TRUE); } } pushInstruction(mb,p); } } for (i++; i < limit; i++) pushInstruction(mb, old[i]); for (; i < slimit; i++) if (old[i]) freeInstruction(old[i]); GDKfree(old); GDKfree(series); #ifdef VLT_DEBUG fprintFunction(stderr,mb,0,LIST_MAL_ALL); #endif /* Defense line against incorrect plans */ /* all new/modified statements are already checked */ //chkTypes(cntxt->usermodule, mb, FALSE); //chkFlow(mb); //chkDeclarations(mb); /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","generator",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return MAL_SUCCEED; }
str OPToltpImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { int i, limit, slimit, updates=0; InstrPtr p, q, lcks; int actions = 0; InstrPtr *old; lng usec = GDKusec(); OLTPlocks wlocks, rlocks; char buf[256]; str msg = MAL_SUCCEED; (void) pci; (void) cntxt; (void) stk; /* to fool compilers */ old= mb->stmt; limit= mb->stop; slimit = mb->ssize; // We use a fake collection of objects to speed up the checking later. OLTPclear(wlocks); OLTPclear(rlocks); for (i = 0; i < limit; i++) { p = old[i]; if( getModuleId(p) == sqlRef && getFunctionId(p) == bindRef) addLock(cntxt,rlocks, mb, p, p->retc + 1, p->retc + 2); else if( getModuleId(p) == sqlRef && getFunctionId(p) == bindidxRef) addLock(cntxt,rlocks, mb, p, p->retc + 1, p->retc + 2); else if( getModuleId(p) == sqlRef && getFunctionId(p) == appendRef ){ addLock(cntxt,wlocks, mb, p, p->retc + 1, p->retc + 2); updates++; } else if( getModuleId(p) == sqlRef && getFunctionId(p) == updateRef ){ addLock(cntxt,wlocks, mb, p, p->retc + 1, p->retc + 2); updates++; } else if( getModuleId(p) == sqlRef && getFunctionId(p) == deleteRef ){ addLock(cntxt,wlocks, mb, p, p->retc + 1, p->retc + 2); updates++; } else if( getModuleId(p) == sqlcatalogRef ){ addLock(cntxt,wlocks, mb, p, 0,0); updates++; } } if( updates == 0) return 0; // Get a free instruction, don't get it from mb lcks= newInstruction(0, oltpRef,lockRef); getArg(lcks,0)= newTmpVariable(mb, TYPE_void); for( i = 0; i< MAXOLTPLOCKS; i++) if( wlocks[i]) lcks = pushInt(mb, lcks, i); else if( rlocks[i]) lcks = pushInt(mb, lcks, -i); if( lcks->argc == 1 ){ freeInstruction(lcks); return MAL_SUCCEED; } // Now optimize the code if ( newMalBlkStmt(mb,mb->ssize + 6) < 0) { freeInstruction(lcks); return 0; } pushInstruction(mb,old[0]); pushInstruction(mb,lcks); for (i = 1; i < limit; i++) { p = old[i]; if( p->token == ENDsymbol){ // unlock all if there is an error q= newCatchStmt(mb,"MALexception"); q= newExitStmt(mb,"MALexception"); q= newCatchStmt(mb,"SQLexception"); q= newExitStmt(mb,"SQLexception"); q= copyInstruction(lcks); if( q == NULL){ for(; i<slimit; i++) if( old[i]) freeInstruction(old[i]); GDKfree(old); throw(MAL,"optimizer.oltp", SQLSTATE(HY001) MAL_MALLOC_FAIL); } setFunctionId(q, releaseRef); pushInstruction(mb,q); } pushInstruction(mb,p); } for(; i<slimit; i++) if( old[i]) freeInstruction(old[i]); GDKfree(old); /* Defense line against incorrect plans */ chkTypes(cntxt->usermodule, mb, FALSE); //chkFlow(mb); //chkDeclarations(mb); /* keep all actions taken as a post block comment */ usec = GDKusec()- usec; snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","oltp",actions, usec); newComment(mb,buf); if( actions >= 0) addtoMalBlkHistory(mb); return msg; }