Ejemplo n.º 1
0
/* barrier blocks can only be dropped when they are fully excluded.  */
static int
OPTremoveUnusedBlocks(Client cntxt, MalBlkPtr mb)
{
	/* catch and remove constant bounded blocks */
	int i, j = 0, action = 0, block = 0, skip = 0, top =0, skiplist[10];
	InstrPtr p;

	for (i = 0; i < mb->stop; i++) {
		p = mb->stmt[i];
		if (blockStart(p)) {
			block++;
			if (p->argc == 2 && isVarConstant(mb, getArg(p, 1)) &&
					getArgType(mb, p, 1) == TYPE_bit &&
					getVarConstant(mb, getArg(p, 1)).val.btval == 0)
			{
				if (skip == 0)
					skip = block;
				action++;
			}
			// Try to remove the barrier statement itself (when true).
			if (p->argc == 2 && isVarConstant(mb, getArg(p, 1)) &&
					getArgType(mb, p, 1) == TYPE_bit &&
					getVarConstant(mb, getArg(p, 1)).val.btval == 1 && 
					top <10 && OPTsimpleflow(mb,i))
			{
				skiplist[top++]= getArg(p,0);
				freeInstruction(p);
				continue;
			}
		}
		if (blockExit(p)) {
			if (top > 0 && skiplist[top-1] == getArg(p,0) ){
				top--;
				freeInstruction(p);
				continue;
			} 
			if (skip )
				freeInstruction(p);
			else
				mb->stmt[j++] = p;
			if (skip == block)
				skip = 0;
			block--;
			if (block == 0)
				skip = 0;
		} else if (skip)
			freeInstruction(p);
		else
			mb->stmt[j++] = p;
	}
	mb->stop = j;
	for (; j < i; j++)
		mb->stmt[j] = NULL;
	if (action) {
		chkTypes(cntxt->fdout, cntxt->nspace, mb, TRUE);
		return mb->errors ? 0 : action;
	}
	return action;
}
Ejemplo n.º 2
0
/* barrier blocks can only be dropped when they are fully excluded.  */
static str
OPTremoveUnusedBlocks(Client cntxt, MalBlkPtr mb)
{
	/* catch and remove constant bounded blocks */
	int i, j = 0, action = 0, block = -1, skip = 0, multipass = 1;
	InstrPtr p;
	str msg = MAL_SUCCEED;

	while(multipass--){
		block = -1;
		skip = 0;
		j = 0;
		for (i = 0; i < mb->stop; i++) {
			p = mb->stmt[i];
			if (blockExit(p) && block == getArg(p,0) ){
					block = -1;
					skip = 0;
					freeInstruction(p);
					mb->stmt[i]= 0;
					continue;
			}
			if (p->argc == 2 && blockStart(p) && block < 0 && isVarConstant(mb, getArg(p, 1)) && getArgType(mb, p, 1) == TYPE_bit ){
				if( getVarConstant(mb, getArg(p, 1)).val.btval == 0)
				{
					block = getArg(p,0);
					skip ++;
					action++;
				}
				// Try to remove the barrier statement itself (when true).
				if ( getVarConstant(mb, getArg(p, 1)).val.btval == 1  && OPTsimpleflow(mb,i))
				{
					block = getArg(p,0);
					skip = 0;
					action++;
					freeInstruction(p);
					mb->stmt[i]= 0;
					continue;
				}
			} else 
			if( p->argc == 2 &&  blockStart(p) && block >= 0 && skip == 0 && isVarConstant(mb, getArg(p, 1)) && getArgType(mb, p, 1) == TYPE_bit && multipass == 0)
				multipass++;
			if (skip){
				freeInstruction(p);
				mb->stmt[i]= 0;
			} else
				mb->stmt[j++] = p;
		}
		mb->stop = j;
		for (; j < i; j++)
			mb->stmt[j] = NULL;
	}
	if (action)
		chkTypes(cntxt->usermodule, mb, TRUE);
	return msg;
}
Ejemplo n.º 3
0
int 
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;

	(void) pci;
	(void) cntxt;
	(void) stk;		/* to fool compilers */
	old= mb->stmt;
	limit= mb->stop;
	slimit = mb->ssize;
	if ( newMalBlkStmt(mb,mb->stop) < 0)
		return 0;
	for (i = 0; i < limit; i++) {
		p = old[i];
		if( getModuleId(p) == sqlRef  && getFunctionId(p) == affectedRowsRef) {
			q = newStmt(mb, 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);
			setVarType(mb,getArg(p,0),TYPE_str);
			q = newReturnStmt(mb);
			getArg(q,0)= getArg(p,0);
			pushArgument(mb,q,j);
			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);
			continue;
		}
		pushInstruction(mb,p);
	} 
	for(; i<slimit; i++)
		if (old[i]) 
			freeInstruction(old[i]);
	GDKfree(old);
	return actions;
}
Ejemplo n.º 4
0
int
OPTmultiplexImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	InstrPtr *old, p;
	int i, limit, slimit, actions= 0;
	str msg= MAL_SUCCEED;

	(void) stk;
	(void) pci;

	old = mb->stmt;
	limit = mb->stop;
	slimit = mb->ssize;
	if ( newMalBlkStmt(mb, mb->ssize) < 0 )
		return 0;

	for (i = 0; i < limit; i++) {
		p = old[i];
		if (msg == MAL_SUCCEED && getModuleId(p) == malRef &&
		    getFunctionId(p) == multiplexRef) {

			if ( MANIFOLDtypecheck(cntxt,mb,p) != NULL){
				setFunctionId(p, manifoldRef);
				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);
	if (mb->errors){
		/* rollback */
	}
	GDKfree(msg);
	return mb->errors? 0: actions;
}
Ejemplo n.º 5
0
int 
OPTmatpackImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int v, i, j, limit, slimit;
	InstrPtr p,q;
	int actions = 0;
	InstrPtr *old;
	char *packIncrementRef = putName("packIncrement", 13);

	(void) pci;
	(void) cntxt;
	(void) stk;		/* to fool compilers */
	old= mb->stmt;
	limit= mb->stop;
	slimit = mb->ssize;
	if ( newMalBlkStmt(mb,mb->stop) < 0)
		return 0;
	for (i = 0; i < limit; i++) {
		p = old[i];
		if( getModuleId(p) == matRef  && getFunctionId(p) == packRef && isaBatType(getArgType(mb,p,1))) {
			q = newStmt(mb, matRef, packIncrementRef);
			v = getArg(q,0);
			setVarType(mb,v,getArgType(mb,p,1));
			q = pushArgument(mb, q, getArg(p,1));
			q = pushInt(mb,q, p->argc - p->retc);

			for ( j = 2; j < p->argc; j++) {
				q = newStmt(mb,matRef, packIncrementRef);
				q = pushArgument(mb, q, v);
				q = pushArgument(mb, q, getArg(p,j));
				setVarType(mb,getArg(q,0),getVarType(mb,v));
				v = getArg(q,0);
			}
			getArg(q,0) = getArg(p,0);
			freeInstruction(p);
			continue;
		}
		pushInstruction(mb,p);
	} 
	for(; i<slimit; i++)
		if (old[i]) 
			freeInstruction(old[i]);
	GDKfree(old);
	return actions;
}
Ejemplo n.º 6
0
int
OPTgroupsImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
{
	int i, actions=0;
	InstrPtr q;
	InstrPtr *old, *ref;
	int limit,slimit;

	(void) cntxt;
	(void) stk;
	if (varGetProp(mb, getArg(mb->stmt[0], 0), inlineProp) != NULL) {
		return 0;
	}

	/* beware, new variables and instructions are introduced */
	ref= (InstrPtr*) GDKzalloc(sizeof(InstrPtr) * mb->vtop); /* to find last assignment */
	if ( ref == NULL) {
		return 0;
	}

	old= mb->stmt;
	limit= mb->stop;
	slimit= mb->ssize;
	if ( newMalBlkStmt(mb,mb->ssize) <0) {
		GDKfree(ref);
		return 0;
	}

	for (i = 0; i<limit; i++){
		p= old[i];
		if (getModuleId(p) == groupRef && p->argc == 4 && getFunctionId(p) == subgroupRef ){
			setFunctionId(p, multicolumnsRef);
			ref[getArg(p,0)] = p;
			actions++;
			OPTDEBUGgroups {
				mnstr_printf(cntxt->fdout,"#new groups instruction\n");
				printInstruction(cntxt->fdout,mb, 0, p, LIST_MAL_ALL);
			}
		}
		if (getModuleId(p) == groupRef && p->argc == 5 && getFunctionId(p) == subgroupdoneRef && ref[getArg(p,4)] != NULL){
			/*
			 * Try to expand its argument list with what we have found so far.
			 * This creates a series of derive paths, many of which will be removed during deadcode elimination.
			 */
			q= copyInstruction(ref[getArg(p,4)]);
			q= pushArgument(mb, q, getArg(p,3));
			getArg(q,0) = getArg(p,0);
			getArg(q,1) = getArg(p,1);
			getArg(q,2) = getArg(p,2);
			ref[getArg(q,0)] = q;
			freeInstruction(p);
			p= q;
			OPTDEBUGgroups{
				mnstr_printf(cntxt->fdout,"#new groups instruction extension\n");
				printInstruction(cntxt->fdout,mb, 0, p, LIST_MAL_ALL);
			}
		} 
Ejemplo n.º 7
0
/*
 * After the client initialization has been finished, we can start the
 * interaction protocol. This involves parsing the input in the context
 * of an already defined procedure and upon success, its execution.
 *
 * In essence, this calls for an incremental parsing operation, because
 * we should wait until a complete basic block has been detected.  Test,
 * first collect the instructions before we take them all.
 *
 * In interactive mode, we should remove the instructions before
 * accepting new ones. The function signature remains the same and the
 * symbol table should also not be affected.  Aside from removing
 * instruction, we should also condense the variable stack, i.e.
 * removing at least the temporary variables, but maybe everything
 * beyond a previous defined point.
 *
 * Beware that we have to cleanup the global stack as well. This to
 * avoid subsequent calls to find garbage information.  However, this
 * action is only required after a successful execution.  Otherwise,
 * garbage collection is not needed.
 */
void
MSresetInstructions(MalBlkPtr mb, int start)
{
	int i;
	InstrPtr p;

	for (i = start; i < mb->ssize; i++) {
		p = getInstrPtr(mb, i);
		if (p)
			freeInstruction(p);
		mb->stmt[i] = NULL;
	}
	mb->stop = start;
}
Ejemplo n.º 8
0
/* finalization of the `infos' structure */
int finalizeStructures(t_translation_infos *infos)
{
   if (infos == NULL)
      return ASM_NOT_INITIALIZED_INFO;
   
   if (infos->code != NULL)
   {
      t_list *current_element;
      t_asm_instruction *current_instr;

      /* initialize `data' */
      current_element = infos->code;
      
      while ((current_element != NULL) && (infos->codesize > 0) )
      {
         current_instr = (t_asm_instruction *) LDATA(current_element);
         
         /* free memory associated with the current instruction */
         freeInstruction(current_instr);

         /* update the value of `current_element' */
         current_element = LNEXT(current_element);
         infos->codesize --;
      }

      while (current_element != NULL)
      {
         /* free memory associated with the current data info. */
         freeData((t_asm_data *) LDATA(current_element));
         
         /* update the value of `current_element' */
         current_element = LNEXT(current_element);
      }

      /* free the code and data segment infos */
      freeList(infos->code);
   }
   
   /* remove labels */
   finalizeLabels(infos->labels);
   
   /* free the memory block associated with `infos' */
   _ASM_FREE_FUNCTION(infos);
   
   return ASM_OK;
}
Ejemplo n.º 9
0
int
OPTrecyclerImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
{
	int i, j, cnt, tp, c, actions = 0, marks = 0, delta = 0;
	Lifespan span;
	InstrPtr *old, q;
	int limit, updstmt = 0;
	char *recycled;
	short app_sc = -1, in = 0;
	ValRecord cst;

	(void) cntxt;
	(void) stk;

	limit = mb->stop;
	old = mb->stmt;

	for (i = 1; i < limit; i++) {
		p = old[i];
		if (getModuleId(p) == sqlRef &&
				(getFunctionId(p) == affectedRowsRef ||
				 getFunctionId(p) == exportOperationRef ||
				 getFunctionId(p) == appendRef ||
				 getFunctionId(p) == updateRef ||
				 getFunctionId(p) == deleteRef))
			updstmt = 1;
	}

	span = setLifespan(mb);
	if (span == NULL)
		return 0;

	/* watch out, newly created instructions may introduce new variables */
	recycled = GDKzalloc(sizeof(char) * mb->vtop * 2);
	if (recycled == NULL)
		return 0;
	if (newMalBlkStmt(mb, mb->ssize) < 0) {
		GDKfree(recycled);
		return 0;
	}
	pushInstruction(mb, old[0]);
	mb->recid = recycleSeq++;

	/* create a handle for recycler */
	(void) newFcnCall(mb, "recycle", "prelude");
	in = 1;
	for (i = 1; i < limit; i++) {
		p = old[i];
		if (hasSideEffects(p, TRUE) || isUpdateInstruction(p) || isUnsafeFunction(p)) {
			if (getModuleId(p) == recycleRef) { /*don't inline recycle instr. */
				freeInstruction(p);
				continue;
			}
			pushInstruction(mb, p);
			/*  update instructions are not recycled but monitored*/
			if (isUpdateInstruction(p)) {
				if (getModuleId(p) == batRef &&
					(getArgType(mb, p, 1) == TYPE_bat
					 || isaBatType(getArgType(mb, p, 1)))) {
					recycled[getArg(p, 1)] = 0;
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, getArg(p, 1));
					actions++;
				}
				if (getModuleId(p) == sqlRef) {
					if (getFunctionId(p) == appendRef) {
						if (app_sc >= 0)
							continue;
						else
							app_sc = getArg(p, 2);
					}
					VALset(&cst, TYPE_int, &delta);
					c = defConstant(mb, TYPE_int, &cst);
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, c);
					pushArgument(mb, q, getArg(p, 2));
					pushArgument(mb, q, getArg(p, 3));
					if (getFunctionId(p) == updateRef)
						pushArgument(mb, q, getArg(p, 4));
					actions++;
				}
			}
			/* take care of SQL catalog update instructions */
			if (getModuleId(p) == sqlRef && getFunctionId(p) == catalogRef) {
				tp = *(int *) getVarValue(mb, getArg(p, 1));
				if (tp == 22 || tp == 25) {
					delta = 2;
					VALset(&cst, TYPE_int, &delta);
					c = defConstant(mb, TYPE_int, &cst);
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, c);
					pushArgument(mb, q, getArg(p, 2));
					if (tp == 25)
						pushArgument(mb, q, getArg(p, 3));
					actions++;
				}
			}
			continue;
		}
		if (p->token == ENDsymbol || p->barrier == RETURNsymbol) {
			if (in) {
				/*
				if (updstmt && app_sc >= 0) {
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, app_sc);
					pushArgument(mb, q, app_tbl);
				}
				 */
				(void) newFcnCall(mb, "recycle", "epilogue");
				in = 0;
			}
			pushInstruction(mb, p);
			continue;
		}

		if (p->barrier && p->token != CMDcall) {
			/* never save a barrier unless it is a command and side-effect free */
			pushInstruction(mb, p);
			continue;
		}

		/* don't change instructions in update statements */
		if (updstmt) {
			pushInstruction(mb, p);
			continue;
		}

		/* skip simple assignments */
		if (p->token == ASSIGNsymbol) {
			pushInstruction(mb, p);
			continue;
		}

		if (getModuleId(p) == octopusRef &&
			(getFunctionId(p) == bindRef || getFunctionId(p) == bindidxRef)) {
			recycled[getArg(p, 0)] = 1;
			p->recycle = recycleMaxInterest;
			marks++;
		}
		/* During base table recycling skip marking instructions other than octopus.bind */
		if (baseTableMode) {
			pushInstruction(mb, p);
			continue;
		}

		/* general rule: all arguments are constants or recycled,
		   ignore C pointer arguments from mvc */
		cnt = 0;
		for (j = p->retc; j < p->argc; j++)
			if (recycled[getArg(p, j)] || isVarConstant(mb, getArg(p, j))
					|| ignoreVar(mb, getArg(p, j)))
				cnt++;
		if (cnt == p->argc - p->retc) {
			OPTDEBUGrecycle {
				mnstr_printf(cntxt->fdout, "#recycle instruction\n");
				printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL);
			}
			marks++;
			p->recycle = recycleMaxInterest; /* this instruction is to be monitored */
			for (j = 0; j < p->retc; j++)
				if (getLastUpdate(span, getArg(p, j)) == i)
					recycled[getArg(p, j)] = 1;
		}
		/*
		 * The expected gain is largest if we can re-use selections
		 * on the base tables in SQL. These, however, are marked as
		 * uselect() calls, which only produce the oid head.
		 * For cheap types we preselect using select() and re-map uselect() back
		 * over this temporary.
		 * For the time being for all possible selects encountered
		 * are marked for re-use.
		 */
		/* take care of semantic driven recyling */
		/* for selections check the bat argument only
		   the range is often template parameter*/
		if ((getFunctionId(p) == selectRef ||
					getFunctionId(p) == antiuselectRef ||
					getFunctionId(p) == likeselectRef ||
					getFunctionId(p) == likeRef ||
					getFunctionId(p) == thetaselectRef) &&
				recycled[getArg(p, 1)])
		{
			p->recycle = recycleMaxInterest;
			marks++;
			if (getLastUpdate(span, getArg(p, 0)) == i)
				recycled[getArg(p, 0)] = 1;
		}
		if ((getFunctionId(p) == uselectRef || getFunctionId(p) == thetauselectRef)
				&& recycled[getArg(p, 1)])
		{
			if (!ATOMvarsized(getGDKType(getArgType(mb, p, 2)))) {
				q = copyInstruction(p);
				getArg(q, 0) = newTmpVariable(mb, TYPE_any);
				if (getFunctionId(p) == uselectRef)
					setFunctionId(q, selectRef);
				else
					setFunctionId(q, thetaselectRef);
				q->recycle = recycleMaxInterest;
				marks++;
				recycled[getArg(q, 0)] = 1;
				pushInstruction(mb, q);
				getArg(p, 1) = getArg(q, 0);
				setFunctionId(p, projectRef);
				p->argc = 2;
			}
			p->recycle = recycleMaxInterest;
			marks++;
			if (getLastUpdate(span, getArg(p, 0)) == i)
				recycled[getArg(p, 0)] = 1;
		}

		if (getModuleId(p) == pcreRef) {
			if ((getFunctionId(p) == selectRef && recycled[getArg(p, 2)]) ||
				(getFunctionId(p) == uselectRef && recycled[getArg(p, 2)])) {
				p->recycle = recycleMaxInterest;
				marks++;
				if (getLastUpdate(span, getArg(p, 0)) == i)
					recycled[getArg(p, 0)] = 1;
			} else if (getFunctionId(p) == likeuselectRef && recycled[getArg(p, 1)]) {
				q = copyInstruction(p);
				getArg(q, 0) = newTmpVariable(mb, TYPE_any);
				setFunctionId(q, likeselectRef);
				q->recycle = recycleMaxInterest;
				recycled[getArg(q, 0)] = 1;
				pushInstruction(mb, q);
				getArg(p, 1) = getArg(q, 0);
				setFunctionId(p, projectRef);
				setModuleId(p, algebraRef);
				p->argc = 2;
				p->recycle = recycleMaxInterest;
				marks += 2;
				if (getLastUpdate(span, getArg(p, 0)) == i)
					recycled[getArg(p, 0)] = 1;
			}
		}

		/*
		 * The sql.bind instructions should be handled carefully
		 * The delete and update BATs should not be recycled,
		 * because they may lead to view dependencies that later interferes
		 * with the transaction commits.
		 */
		/* enable recycling of delta-bats
		if (getModuleId(p) == sqlRef &&
				(((getFunctionId(p) == bindRef || getFunctionId(p) == putName("bind_idxbat", 11)) &&
				  getVarConstant(mb, getArg(p, 5)).val.ival != 0) ||
				 getFunctionId(p) == binddbatRef)) {
			recycled[getArg(p, 0)] = 0;
			p->recycle = REC_NO_INTEREST;
		}
		*/

/*
 * The sql.bind instructions should be handled carefully
 * The delete and update BATs should not be recycled,
 * because they may lead to view dependencies that later interferes
 * with the transaction commits.
 */
/* enable recycling of delta-bats
		if (getModuleId(p)== sqlRef && 
			(((getFunctionId(p)==bindRef || getFunctionId(p) == putName("bind_idxbat",11)) && 
				getVarConstant(mb, getArg(p,5)).val.ival != 0) ||
				getFunctionId(p)== binddbatRef) ) {
				recycled[getArg(p,0)]=0;
				p->recycle = REC_NO_INTEREST; 
			}
*/

		pushInstruction(mb, p);
	}
Ejemplo n.º 10
0
int 
OPTquerylogImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i, limit, slimit;
	InstrPtr p = 0, *old= mb->stmt, q,r;
	int argc, io, user,nice,sys,idle,iowait,load, arg, start,finish, name;
	int xtime=0, rtime = 0, tuples=0;
	InstrPtr defineQuery = NULL;


	// query log needed?
	if ( !QLOGisset() )
		return 0;
	(void) pci;
	(void) stk;		/* to fool compilers */
	(void) cntxt;
	/* gather information */
	for (i = 1; i < mb->stop; i++) {
		p = getInstrPtr(mb,i);
		if ( getModuleId(p) && idcmp(getModuleId(p), "querylog") == 0 && idcmp(getFunctionId(p),"define")==0){
			defineQuery= p;
			getVarConstant(mb,getArg(p,3)).val.lval = GDKusec()-getVarConstant(mb,getArg(p,3)).val.lval ;
		}
	}
	if ( defineQuery == NULL)
		/* nothing to do */
		return 0;

	limit= mb->stop;
	slimit= mb->ssize;
	if ( newMalBlkStmt(mb, mb->ssize) < 0)
		return 0; 

	pushInstruction(mb, old[0]);
	/* run the querylog.define operation */
	defineQuery = copyInstruction(defineQuery);
	setFunctionId(defineQuery, insertRef);
	getArg(defineQuery,0) = newTmpVariable(mb,TYPE_any);
	defineQuery->token = ASSIGNsymbol;
	setModuleId(defineQuery,querylogRef);

	/* collect the initial statistics */
	q = newStmt(mb, "clients", "getUsername");
	name= getArg(q,0)= newVariable(mb,GDKstrdup("name"),TYPE_str);
	defineQuery = pushArgument(mb,defineQuery,name);
	q = newStmt(mb, "mtime", "current_timestamp");
	start= getArg(q,0)= newVariable(mb,GDKstrdup("start"),TYPE_timestamp);
	defineQuery = pushArgument(mb,defineQuery,start);
	pushInstruction(mb, defineQuery);

	q = newStmt1(mb, sqlRef, "argRecord");
	for ( argc=1; argc < old[0]->argc; argc++)
		q = pushArgument(mb, q, getArg(old[0],argc));

	arg= getArg(q,0)= newVariable(mb,GDKstrdup("args"),TYPE_str);


	q = newStmt(mb, "alarm", "usec");
	xtime = getArg(q,0)= newVariable(mb,GDKstrdup("xtime"),TYPE_lng);
	user = newVariable(mb,GDKstrdup("user"),TYPE_lng);
	nice = newVariable(mb,GDKstrdup("nice"),TYPE_lng);
	sys = newVariable(mb,GDKstrdup("sys"),TYPE_lng);
	idle = newVariable(mb,GDKstrdup("idle"),TYPE_lng);
	iowait = newVariable(mb,GDKstrdup("iowait"),TYPE_lng);
	q = newStmt(mb, "profiler", "cpustats");
	q->retc= q->argc =0;
	q = pushReturn(mb,q,user);
	q = pushReturn(mb,q,nice);
	q = pushReturn(mb,q,sys);
	q = pushReturn(mb,q,idle);
	q = pushReturn(mb,q,iowait);
	q = newAssignment(mb);
	tuples= getArg(q,0) = newVariable(mb,GDKstrdup("tuples"),TYPE_wrd);
	(void) pushWrd(mb,q,1);

	for (i = 1; i < limit; i++) {
		p = old[i];
		
		if (getModuleId(p)==sqlRef && 
			(idcmp(getFunctionId(p),"exportValue")==0 ||
			 idcmp(getFunctionId(p),"exportResult")==0  ) ) {

			q = newStmt(mb, "alarm", "usec");
			r = newStmt1(mb, calcRef, "-");
			r = pushArgument(mb, r, getArg(q,0));
			r = pushArgument(mb, r, xtime);
			getArg(r,0)=xtime;

			q = newStmt(mb, "alarm", "usec");
			rtime= getArg(q,0)= newVariable(mb,GDKstrdup("rtime"),TYPE_lng);
			pushInstruction(mb,p);
			continue;
		}
		if ( getModuleId(p) == sqlRef && idcmp(getFunctionId(p),"resultSet")==0  && isaBatType(getVarType(mb,getArg(p,3)))){
			q = newStmt(mb, "aggr", "count");
			getArg(q,0) = tuples;
			(void) pushArgument(mb,q, getArg(p,3));
			pushInstruction(mb,p);
			continue;
		}	
		if ( p->token== ENDsymbol || p->barrier == RETURNsymbol || p->barrier == YIELDsymbol){
			if ( rtime == 0){
				q = newStmt(mb, "alarm", "usec");
				r = newStmt1(mb, calcRef, "-");
				r = pushArgument(mb, r, getArg(q,0));
				r = pushArgument(mb, r, xtime);
				getArg(r,0)=xtime;
				q = newStmt(mb, "alarm", "usec");
				rtime= getArg(q,0)= newVariable(mb,GDKstrdup("rtime"),TYPE_lng);
			}
			q = newStmt(mb, "alarm", "usec");
			r = newStmt1(mb, calcRef, "-");
			r = pushArgument(mb, r, getArg(q,0));
			r = pushArgument(mb, r, rtime);
			getArg(r,0)=rtime;
			/*
			 * Post execution statistics gathering
			 */
			q = newStmt(mb, "mtime", "current_timestamp");
			finish= getArg(q,0)= newVariable(mb,GDKstrdup("finish"),TYPE_any);

			q = newStmt(mb, "profiler", "cpuload");
			load = newVariable(mb,GDKstrdup("load"),TYPE_int);
			getArg(q,0)= load;
			io = newVariable(mb,GDKstrdup("io"),TYPE_int);
			q= pushReturn(mb,q,io);
			q = pushArgument(mb,q,user);
			q = pushArgument(mb,q,nice);
			q = pushArgument(mb,q,sys);
			q = pushArgument(mb,q,idle);
			q = pushArgument(mb,q,iowait);

			q = newStmt(mb, querylogRef, "call");
			q = pushArgument(mb, q, start);
			q = pushArgument(mb, q, finish); 
			q = pushArgument(mb, q, arg);
			q = pushArgument(mb, q, tuples); 
			q = pushArgument(mb, q, xtime); 
			q = pushArgument(mb, q, rtime); 
			q = pushArgument(mb, q, load); 
			q = pushArgument(mb, q, io); 
			pushInstruction(mb,p);
			continue;
		}

		pushInstruction(mb,p);
		if (p->barrier == YIELDsymbol){
			/* the factory yield may return */
			q = newStmt(mb, "mtime", "current_timestamp");
			start= getArg(q,0)= newVariable(mb,GDKstrdup("start"),TYPE_any);
			q = newStmt1(mb, sqlRef, "argRecord");
			for ( argc=1; argc < old[0]->argc; argc++)
				q = pushArgument(mb, q, getArg(old[0],argc));
			arg= getArg(q,0)= newVariable(mb,GDKstrdup("args"),TYPE_str);
			q = newAssignment(mb);
			q = pushLng(mb,q,0);
			q = newAssignment(mb);
			q = pushWrd(mb,q,0);
			tuples= getArg(q,0)= newVariable(mb,GDKstrdup("tuples"),TYPE_wrd);
			newFcnCall(mb,"profiler","setMemoryFlag");
			q->argc--;
			pushWrd(mb,q,1);
			q = newStmt(mb, "alarm", "usec");
			xtime = getArg(q,0)= newVariable(mb,GDKstrdup("xtime"),TYPE_lng);
		}
	}

	for( ; i<slimit; i++)
		if(old[i])
			freeInstruction(old[i]);
	GDKfree(old);
	return 1;
}
Ejemplo n.º 11
0
/*
 * Macro inversions map a consecutive sequences of MAL instructions
 * into a single call. Subsequent resolution will bind it with the proper
 * function. The pattern being replaced should be a self-standing
 * assignment. [could be improved]
 *
 * The function being replaced should assign the result to
 * the signature variables. Otherwise it will be difficult
 * to assess which result to retain.
 */
static int
replaceMALblock(MalBlkPtr mb, int pc, MalBlkPtr mc)
{
	int i, j, k, lim;
	InstrPtr p, q, rq;
	int *cvar, *mvar;
	int ctop = 0, mtop = 0;

	/* collect variable map */
	cvar = (int *) GDKmalloc(mc->vtop * mc->maxarg * sizeof(*cvar));
	if (cvar == NULL)
		return -1;
	mvar = (int *) GDKmalloc(mb->vtop * mc->maxarg * sizeof(*mvar));
	if (mvar == NULL){
		GDKfree(cvar);
		return -1;
	}
	lim = pc + mc->stop - 3;
	k = 1;
	for (i = pc; i < lim; i++, k++) {
		p = getInstrPtr(mb, i);
		q = getInstrPtr(mc, k);
		for (j = 0; j < q->argc; j++)
			cvar[ctop++] = getArg(q, j);
		assert(ctop < mc->vtop *mc->maxarg);

		for (j = 0; j < p->argc; j++)
			mvar[mtop++] = getArg(p, j);
	}
	assert(mtop == ctop);	/*shouldn't happen */

	p = getInstrPtr(mb, pc);
	q = copyInstruction(getInstrPtr(mc, 0));	/* the signature */
	q->token = ASSIGNsymbol;
	mb->stmt[pc] = q;

	for (i = q->retc; i < q->argc; i++)
		for (j = 0; j < ctop; j++)
			if (q->argv[i] == cvar[j]) {
				q->argv[i] = mvar[j];
				break;
			}
	/* take the return expression  and match the variables*/
	rq = getInstrPtr(mc, mc->stop - 2);
	for (i = 0; i < rq->retc; i++)
		for (j = 0; j < ctop; j++)
			if (rq->argv[i+rq->retc] == cvar[j]) {
				q->argv[i] = mvar[j];
				break;
			}
	freeInstruction(p);

	/* strip signature, return, and end statements */
	k = mc->stop - 3;
	j = pc + k;
	for (i = pc + 1; i < pc + k; i++)
		freeInstruction(mb->stmt[i]);

	for (i = pc + 1; i < mb->stop - k; i++)
		mb->stmt[i] = mb->stmt[j++];

	k = i;
	for (; i < mb->stop; i++)
		mb->stmt[i] = 0;

	mb->stop = k;
	GDKfree(cvar);
	GDKfree(mvar);
	return pc;
}
Ejemplo n.º 12
0
int
inlineMALblock(MalBlkPtr mb, int pc, MalBlkPtr mc)
{
	int i, k, l, n;
	InstrPtr *ns, p,q;
	int *nv, *np = NULL;

	p = getInstrPtr(mb, pc);
	q = getInstrPtr(mc, 0);
	ns = GDKzalloc((l = (mb->ssize + mc->ssize + p->retc - 3)) * sizeof(InstrPtr));
	if (ns == NULL)
		return -1;
	if ( mc->ptop > 0){
		np = (int*) GDKmalloc(mc->ptop * sizeof(int));
		if (np == 0){
			GDKfree(ns);
			return -1;
		}
	}
	nv = (int*) GDKmalloc(mc->vtop * sizeof(int));
	if (nv == 0){
		GDKfree(ns);
		if( np)
			GDKfree(np);
		return -1;
	}

	/* add all properties of the new block to the target environment */
	for (n = 0; n < mc->ptop; n++) {
		int propid = newProperty(mb);

		if (propid < 0) {
			assert(0);
			return -1;
		}
		np[n] = propid; 
		mb->prps[propid].idx = mc->prps[n].idx;
		mb->prps[propid].op = mc->prps[n].op;
		mb->prps[propid].var = mc->prps[n].var; /* fixed later */
	}

	/* add all variables of the new block to the target environment */
	for (n = 0; n < mc->vtop; n++) {
		VarPtr ov, v;

		if (isExceptionVariable(mc->var[n]->name)) {
			nv[n] = newVariable(mb,GDKstrdup(mc->var[n]->name),TYPE_str);
			if (isVarUDFtype(mc,n))
				setVarUDFtype(mb,nv[n]);
			if (isVarUsed(mc,n))
				setVarUsed(mb,nv[n]);
		} else if (isVarTypedef(mc,n)) {
			nv[n] = newTypeVariable(mb,getVarType(mc,n));
		} else if (isVarConstant(mc,n)) {
			nv[n] = cpyConstant(mb,getVar(mc,n));
		} else {
			nv[n] = newTmpVariable(mb, getVarType(mc, n));
			if (isVarUDFtype(mc,n))
				setVarUDFtype(mb,nv[n]);
			if (isVarUsed(mc,n))
				setVarUsed(mb,nv[n]);
		}
		/* remap the properties */
		ov = getVar(mc, n);
		v = getVar(mb, nv[n]);
		if (ov->propc > v->maxprop) {
			int size = sizeof(VarRecord);
        		VarPtr vnew = (VarPtr) GDKzalloc(size + ov->propc * sizeof(int));
			memcpy((char*) vnew, (char*) v, size);
			vnew->maxprop = ov->propc;
			mb->var[nv[n]] = vnew;
			GDKfree(v);
			v = getVar(mb, nv[n]);
		}
		for (i = 0; i < ov->propc; i++) 
			v->prps[i] = np[ov->prps[i]];
		v->propc = ov->propc;
	}

	/* change the property variables to the new context */
	for (n = 0; n < mc->ptop; n++) {
		if (mc->prps[n].var)
			mb->prps[np[n]].var = nv[mc->prps[n].var];
		assert( mb->prps[np[n]].var >= 0);
	}

	/* use an alias mapping to keep track of the actual arguments */
	for (n = p->retc; n < p->argc; n++)
		nv[getArg(q,n)] = getArg(p, n);

	k = 0;
	/* find the return statement of the inline function */
	for (i = 1; i < mc->stop - 1; i++) {
		q = mc->stmt[i];
		if( q->barrier== RETURNsymbol || q->barrier== YIELDsymbol){
			/* add the mapping of the return variables */
			for(n=0; n<p->retc; n++)
				nv[getArg(q,n)] = getArg(p,n);
		}
	}

	/* copy the stable part */
	for (i = 0; i < pc; i++)
		ns[k++] = mb->stmt[i];

	for (i = 1; i < mc->stop - 1; i++) {
		q = mc->stmt[i];
		if( q->token == ENDsymbol)
			break;

		/* copy the instruction and fix variable references */
		ns[k] = copyInstruction(q);
		for (n = 0; n < q->argc; n++)
			getArg(ns[k], n) = nv[getArg(q, n)];

		if (q->barrier == RETURNsymbol || q->barrier == YIELDsymbol) {
			for(n=0; n<q->retc; n++)
				clrVarFixed(mb,getArg(ns[k],n)); /* for typing */
			setModuleId(ns[k],getModuleId(q));
			setFunctionId(ns[k],getFunctionId(q));
			ns[k]->barrier = 0;
			ns[k]->token = ASSIGNsymbol;
		}
		k++;
	} 

	/* copy the remainder of the stable part */
	freeInstruction(p);
	for (i = pc + 1; i < mb->stop; i++){
		ns[k++] = mb->stmt[i];
	}
	/* remove any free instruction */
	for(; i<mb->ssize; i++)
	if( mb->stmt[i]){
		freeInstruction(mb->stmt[i]);
		mb->stmt[i]= 0;
	}
	GDKfree(mb->stmt);
	mb->stmt = ns;

	mb->ssize = l;
	mb->stop = k;
	GDKfree(np);
	GDKfree(nv);
	return pc;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
str OPTwrapper (Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){
	str modnme = "(NONE)";
	str fcnnme = 0;
	str msg= MAL_SUCCEED;
	Symbol s= NULL;
	lng t,clk= GDKusec();
	int i, actions = 0;
	char optimizer[256];
	InstrPtr q;

	if( p == NULL)
		throw(MAL, "opt_wrapper", "missing optimizer statement");
	snprintf(optimizer,256,"%s", fcnnme = getFunctionId(p));
	q= copyInstruction(p);
	OPTIMIZERDEBUG 
		mnstr_printf(cntxt->fdout,"=APPLY OPTIMIZER %s\n",fcnnme);
	if( p && p->argc > 1 ){
		if( getArgType(mb,p,1) != TYPE_str ||
			getArgType(mb,p,2) != TYPE_str ||
			!isVarConstant(mb,getArg(p,1)) ||
			!isVarConstant(mb,getArg(p,2))
			) {
			freeInstruction(q);
			throw(MAL, optimizer, ILLARG_CONSTANTS);
		}

		if( stk != 0){
			modnme= *getArgReference_str(stk,p,1);
			fcnnme= *getArgReference_str(stk,p,2);
		} else {
			modnme= getArgDefault(mb,p,1);
			fcnnme= getArgDefault(mb,p,2);
		}
		removeInstruction(mb, p);
		s= findSymbol(cntxt->nspace, putName(modnme,strlen(modnme)),putName(fcnnme,strlen(fcnnme)));

		if( s == NULL) {
			freeInstruction(q);
			throw(MAL, optimizer, RUNTIME_OBJECT_UNDEFINED ":%s.%s", modnme, fcnnme);
		}
		mb = s->def;
		stk= 0;
	} else if( p ) 
		removeInstruction(mb, p);
	if( mb->errors ){
		/* when we have errors, we still want to see them */
		addtoMalBlkHistory(mb,getModuleId(q));
		freeInstruction(q);
		return MAL_SUCCEED;
	}


	for ( i=0; codes[i].nme; i++)
		if ( strcmp(codes[i].nme, optimizer)== 0 ){
			actions = (int)(*(codes[i].fcn))(cntxt, mb, stk,0);
			break;	
		}
	if ( codes[i].nme == 0){
		freeInstruction(q);
		throw(MAL, optimizer, RUNTIME_OBJECT_UNDEFINED ":%s.%s", modnme, fcnnme);
	}

	msg= optimizerCheck(cntxt, mb, optimizer, actions, t=(GDKusec() - clk));
	OPTIMIZERDEBUG {
		mnstr_printf(cntxt->fdout,"=FINISHED %s  %d\n",optimizer, actions);
		printFunction(cntxt->fdout,mb,0,LIST_MAL_DEBUG );
	}
	DEBUGoptimizers
		mnstr_printf(cntxt->fdout,"#optimizer %-11s %3d actions %5d MAL instructions ("SZFMT" K) " LLFMT" usec\n", optimizer, actions, mb->stop, 
		((sizeof( MalBlkRecord) +mb->ssize * offsetof(InstrRecord, argv)+ mb->vtop * sizeof(int) /* argv estimate */ +mb->vtop* sizeof(VarRecord) + mb->vsize*sizeof(VarPtr)+1023)/1024),
		t);
	QOTupdateStatistics(getModuleId(q),actions,t);
	addtoMalBlkHistory(mb,getModuleId(q));
	freeInstruction(q);
	return msg;
}
Ejemplo n.º 15
0
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;
}
Ejemplo n.º 16
0
static int
OPTsql_appendImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	InstrPtr *old = NULL;
	int i, limit, slimit, actions = 0;

	(void) pci; /* Tell compilers that we know that we do not */
	(void) stk; /* use these function parameters, here.       */

	/* In general, a MAL optimizer transforms a given MAL program into a
	 * modified one by sequentially walking through the given program
	 * and concurrently creating a new one from scratch by
	 * (1) copying statements as is, modified, or in a different order,
	 * or (2) omitting statements or (3) introducing new statements.
	 */

	/* check for logical error: mb must never be NULL */
	assert (mb != NULL);

	/* save the old stage of the MAL block */
	old = mb->stmt;
	limit= mb->stop;
	slimit = mb->ssize;

	/* initialize the statement list. Notice, the symbol table remains intact */
	if (newMalBlkStmt(mb, mb->ssize) < 0)
		return 0;

	/* the plan signature can be copied safely */
	pushInstruction(mb, old[0]);

	/* iterate over the instructions of the input MAL program */
	for (i = 1; i < limit; i++) {
		InstrPtr p = old[i];

		/* check for
		 *  v3 := sql.append( ..., ..., ..., ..., v0 );
		 */
		if (getModuleId(p) == sqlRef &&
		    getFunctionId(p) == appendRef &&
		    p->argc > 5 &&
		    p->retc == 1 &&
		    isaBatType(getArgType(mb, p, 5))) {
			/* found
			 *  v3 := sql.append( ..., ..., ..., ..., v0 );
			 */
			int j = 0, k = 0;
			InstrPtr q1 = NULL, q2 = NULL;
			bit found = FALSE;

			/* check whether next is
			 *  v4 := aggr.count(v0);
			 */
			if (i+1 < limit) {
				InstrPtr q = old[i+1];
				if (getModuleId(q) == aggrRef &&
				    getFunctionId(q) == countRef &&
				    q->argc == 2 &&
				    q->retc == 1 &&
				    getArg(q, 1) == getArg(p, 5)) {
					/* found
					 *  v3 := sql.append( ..., ..., ..., ..., v0 );
					 *  v4 := aggr.count(v0);
					 */
					/* issue/execute
					 *  v4 := aggr.count(v0);
					 * before
					 *  v3 := sql.append( ..., ..., ..., ..., v0 );
					 */
					pushInstruction(mb, q);
					q1 = q;
					i++;
					actions++;	/* to keep track if anything has been done */
				}
			}

			/* look for
			 *  v5 := ... v0 ...;
			 */
			/* an expensive loop, better would be to remember that v0
			 * has a different role.  A typical method is to keep a
			 * map from variable -> instruction where it was
			 * detected. Then you can check each assignment for use of
			 * v0
			*/
			for (j = i+1; !found  && j < limit; j++)
				for (k = old[j]->retc; !found && k < old[j]->argc; k++)
					found = (getArg(old[j], k) == getArg(p, 5));
			if (found) {
				/* replace
				 *  v3 := sql.append( ..., ..., ..., ..., v0 );
				 * with
				 *  v1 := aggr.count( v0 );
				 *  v2 := algebra.slice( v0, 0, v1 );
				 *  v3 := sql.append( ..., ..., ..., ..., v2 );
				 */

				/* push new v1 := aggr.count( v0 ); unless already available */
				if (q1 == NULL) {
					/* use mal_builder.h primitives
					 * q1 = newStmt(mb, aggrRef,countRef);
					 * setArgType(mb,q1,TYPE_wrd) */
					/* it will be added to the block and even my
					 * re-use MAL instructions */
					q1 = newInstruction(mb,ASSIGNsymbol);
					getArg(q1,0) = newTmpVariable(mb, TYPE_wrd);
					setModuleId(q1, aggrRef);
					setFunctionId(q1, countRef);
					q1 = pushArgument(mb, q1, getArg(p, 5));
					pushInstruction(mb, q1);
				}

				/* push new v2 := algebra.slice( v0, 0, v1 ); */
				/* use mal_builder.h primitives
				 * q1 = newStmt(mb, algebraRef,sliceRef); */
				q2 = newInstruction(mb,ASSIGNsymbol);
				getArg(q2,0) = newTmpVariable(mb, TYPE_any);
				setModuleId(q2, algebraRef);
				setFunctionId(q2, sliceRef);
				q2 = pushArgument(mb, q2, getArg(p, 5));
				q2 = pushWrd(mb, q2, 0);
				q2 = pushArgument(mb, q2, getArg(q1, 0));
				pushInstruction(mb, q2);

				/* push modified v3 := sql.append( ..., ..., ..., ..., v2 ); */
				getArg(p, 5) = getArg(q2, 0);
				pushInstruction(mb, p);

				actions++;
				continue;
			}
		}

		pushInstruction(mb, p);
		if (p->token == ENDsymbol) break;
	}

	/* We would like to retain everything from the ENDsymbol
	 * up to the end of the plan, because after the ENDsymbol
	 * the remaining optimizer steps are stored.
	 */
	for(i++; i<limit; i++)
		if (old[i])
			pushInstruction(mb, old[i]);
	/* any remaining MAL instruction records are removed */
	for(; i<slimit; i++)
		if (old[i])
			freeInstruction(old[i]);

	GDKfree(old);

	/* for statistics we return if/how many patches have been made */
	DEBUGoptimizers
		mnstr_printf(cntxt->fdout,"#opt_sql_append: %d statements added\n",
				actions);
	return actions;
}
Ejemplo n.º 17
0
/*
 * Keeping variables around beyond their end-of-life-span
 * can be marked with the proper 'keep'.
 */
int
OPTgarbageCollectorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i, j, k, n = 0, limit, vlimit, depth=0, slimit;
	InstrPtr p, q, *old;
	int actions = 0;
	Lifespan span;

	(void) pci;
	(void) cntxt;
	(void) stk;
	if (varGetProp(mb, getArg(mb->stmt[0], 0), inlineProp) != NULL)
		return 0;

	span = setLifespan(mb);
	if ( span == NULL)
		return 0;

	old= mb->stmt;
	limit = mb->stop;
	slimit = mb->ssize;
	vlimit = mb->vtop;
	if ( newMalBlkStmt(mb,mb->ssize) < 0) {
		GDKfree(span);
		return 0;
	}

	p = NULL;
	for (i = 0; i < limit; i++) {
		p = old[i];
		p->gc &=  ~GARBAGECONTROL;

		if ( p->barrier == RETURNsymbol){
			pushInstruction(mb, p);
			continue;
		}
		if (blockStart(p) )
			depth++;
		if ( p->token == ENDsymbol)
			break;
		
		pushInstruction(mb, p);
		n = mb->stop-1;
		for (j = 0; j < p->argc; j++) {
			if (getEndLifespan(span,getArg(p,j)) == i && isaBatType(getArgType(mb, p, j)) ){
				mb->var[getArg(p,j)]->eolife = n;
				p->gc |= GARBAGECONTROL;
			} 
		}
		if (blockExit(p) ){
			/* force garbage collection of all within upper block */
			depth--;
			for (k = 0; k < vlimit; k++) {
				if (getBeginLifespan(span,k) > 0  &&
					getEndLifespan(span,k) == i &&
					isaBatType(getVarType(mb,k)) &&
					varGetProp(mb, k, keepProp) == NULL){
						q= newAssignment(mb);
						getArg(q,0) = k;
						setVarUDFtype(mb,k);
						setVarFixed(mb,k);
						q= pushNil(mb,q, getVarType(mb,k));
						q->gc |= GARBAGECONTROL;
						mb->var[k]->eolife = mb->stop-1;
						actions++;
				}
			}
		}
	}
	assert(p);
	assert( p->token == ENDsymbol);
	pushInstruction(mb, p);
	for (i++; i < limit; i++) 
		pushInstruction(mb, old[i]);
	for (; i < slimit; i++) 
		if (old[i])
			freeInstruction(old[i]);
	getInstrPtr(mb,0)->gc |= GARBAGECONTROL;
	GDKfree(old);
	OPTDEBUGgarbageCollector{ 
		int k;
		mnstr_printf(cntxt->fdout, "#Garbage collected BAT variables \n");
		for ( k =0; k < vlimit; k++)
		mnstr_printf(cntxt->fdout,"%10s eolife %3d  begin %3d lastupd %3d end %3d\n",
			getVarName(mb,k), mb->var[k]->eolife,
			getBeginLifespan(span,k), getLastUpdate(span,k), getEndLifespan(span,k));
		mnstr_printf(cntxt->fdout, "End of GCoptimizer\n");
	}
	GDKfree(span);

	return actions+1;
}
Ejemplo n.º 18
0
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;
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
int
OPTpushselectImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i, j, limit, slimit, actions=0, *vars, push_down_delta = 0, nr_topn = 0, nr_likes = 0;
	InstrPtr p, *old;
	subselect_t subselects;

	memset(&subselects, 0, sizeof(subselects));
	if( mb->errors) 
		return 0;

	OPTDEBUGpushselect
		mnstr_printf(cntxt->fdout,"#Push select optimizer started\n");
	(void) stk;
	(void) pci;
	vars= (int*) GDKzalloc(sizeof(int)* mb->vtop);
	if( vars == NULL)
		return 0;

	limit = mb->stop;
	slimit= mb->ssize;
	old = mb->stmt;

	/* check for bailout conditions */
	for (i = 1; i < limit; i++) {
		int lastbat;
		p = old[i];

		for (j = 0; j<p->retc; j++) {
 			int res = getArg(p, j);
			vars[res] = i;
		}

		if (getModuleId(p) == algebraRef && 
			(getFunctionId(p) == tintersectRef || getFunctionId(p) == tinterRef || 
			 getFunctionId(p) == tdifferenceRef || getFunctionId(p) == tdiffRef)) {
			GDKfree(vars);
			return 0;
		}

		if (getModuleId(p) == algebraRef && getFunctionId(p) == sliceRef)
			nr_topn++;

		if (isLikeOp(p))
			nr_likes++;

		if (getModuleId(p) == sqlRef && getFunctionId(p) == deltaRef)
			push_down_delta++;

		if (getModuleId(p) == sqlRef && getFunctionId(p) == tidRef) { /* rewrite equal table ids */
			int sname = getArg(p, 2), tname = getArg(p, 3), s;

			for (s = 0; s < subselects.nr; s++) {
				InstrPtr q = old[vars[subselects.tid[s]]];
				int Qsname = getArg(q, 2), Qtname = getArg(q, 3);

				if (no_updates(old, vars, getArg(q,1), getArg(p,1)) &&
				    ((sname == Qsname && tname == Qtname) ||
				    (0 && strcmp(getVarConstant(mb, sname).val.sval, getVarConstant(mb, Qsname).val.sval) == 0 &&
				     strcmp(getVarConstant(mb, tname).val.sval, getVarConstant(mb, Qtname).val.sval) == 0))) {
					clrFunction(p);
					p->retc = 1;
					p->argc = 2;
					getArg(p, 1) = getArg(q, 0);
					break;
				}
			}
		}
		lastbat = lastbat_arg(mb, p);
		if (isSubSelect(p) && p->retc == 1 &&
		   /* no cand list */ getArgType(mb, p, lastbat) != newBatType(TYPE_oid, TYPE_oid)) {
			int i1 = getArg(p, 1), tid = 0;
			InstrPtr q = old[vars[i1]];

			/* find the table ids */
			while(!tid) {
				if (getModuleId(q) == algebraRef && getFunctionId(q) == leftfetchjoinRef) {
					int i1 = getArg(q, 1);
					InstrPtr s = old[vars[i1]];
	
					if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef) 
						tid = getArg(q, 1);
					if (s->argc == 2 && s->retc == 1) {
						int i1 = getArg(s, 1);
						InstrPtr s = old[vars[i1]];
						if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef) 
							tid = getArg(q, 1);
					}
					break;
				} else if (isMapOp(q) && q->argc >= 2 && isaBatType(getArgType(mb, q, 1))) {
					int i1 = getArg(q, 1);
					q = old[vars[i1]];
				} else if (isMapOp(q) && q->argc >= 3 && isaBatType(getArgType(mb, q, 2))) {
					int i2 = getArg(q, 2);
					q = old[vars[i2]];
				} else {
					break;
				}
			}
			if (tid && subselect_add(&subselects, tid, getArg(p, 0)) < 0) {
				GDKfree(vars);
				return 0;
			}
		}
		/* left hand side */
		if ( (GDKdebug & (1<<15)) &&
		     isMatJoinOp(p) && p->retc == 2) { 
			int i1 = getArg(p, 2), tid = 0;
			InstrPtr q = old[vars[i1]];

			/* find the table ids */
			while(!tid) {
				if (getModuleId(q) == algebraRef && getFunctionId(q) == leftfetchjoinRef) {
					int i1 = getArg(q, 1);
					InstrPtr s = old[vars[i1]];
	
					if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef) 
						tid = getArg(q, 1);
					break;
				} else if (isMapOp(q) && q->argc >= 2 && isaBatType(getArgType(mb, q, 1))) {
					int i1 = getArg(q, 1);
					q = old[vars[i1]];
				} else if (isMapOp(q) && q->argc >= 3 && isaBatType(getArgType(mb, q, 2))) {
					int i2 = getArg(q, 2);
					q = old[vars[i2]];
				} else {
					break;
				}
			}
			if (tid && subselect_add(&subselects, tid, getArg(p, 0)) < 0) {
				GDKfree(vars);
				return 0;
			}
		}
		/* right hand side */
		if ( (GDKdebug & (1<<15)) &&
		     isMatJoinOp(p) && p->retc == 2) { 
			int i1 = getArg(p, 3), tid = 0;
			InstrPtr q = old[vars[i1]];

			/* find the table ids */
			while(!tid) {
				if (getModuleId(q) == algebraRef && getFunctionId(q) == leftfetchjoinRef) {
					int i1 = getArg(q, 1);
					InstrPtr s = old[vars[i1]];
	
					if (getModuleId(s) == sqlRef && getFunctionId(s) == tidRef) 
						tid = getArg(q, 1);
					break;
				} else if (isMapOp(q) && q->argc >= 2 && isaBatType(getArgType(mb, q, 1))) {
					int i1 = getArg(q, 1);
					q = old[vars[i1]];
				} else if (isMapOp(q) && q->argc >= 3 && isaBatType(getArgType(mb, q, 2))) {
					int i2 = getArg(q, 2);
					q = old[vars[i2]];
				} else {
					break;
				}
			}
			if (tid && subselect_add(&subselects, tid, getArg(p, 1)) < 0) {
				GDKfree(vars);
				return 0;
			}
		}
	}

	if ((!subselects.nr && !nr_topn && !nr_likes) || newMalBlkStmt(mb, mb->ssize) <0 ) {
		GDKfree(vars);
		return 0;
	}
	pushInstruction(mb,old[0]);

	for (i = 1; i < limit; i++) {
		p = old[i];

		/* rewrite batalgebra.like + subselect -> likesubselect */
		if (getModuleId(p) == algebraRef && p->retc == 1 && getFunctionId(p) == subselectRef) { 
			int var = getArg(p, 1);
			InstrPtr q = mb->stmt[vars[var]]; /* BEWARE: the optimizer may not add or remove statements ! */

			if (isLikeOp(q)) { /* TODO check if getArg(p, 3) value == TRUE */
				InstrPtr r = newInstruction(mb, ASSIGNsymbol);
				int has_cand = (getArgType(mb, p, 2) == newBatType(TYPE_oid, TYPE_oid)); 
				int a, anti = (getFunctionId(q)[0] == 'n'), ignore_case = (getFunctionId(q)[anti?4:0] == 'i');

				setModuleId(r, algebraRef);
				setFunctionId(r, likesubselectRef);
				getArg(r,0) = getArg(p,0);
				r = pushArgument(mb, r, getArg(q, 1));
				if (has_cand)
					r = pushArgument(mb, r, getArg(p, 2));
				for(a = 2; a<q->argc; a++)
					r = pushArgument(mb, r, getArg(q, a));
				if (r->argc < (4+has_cand))
					r = pushStr(mb, r, ""); /* default esc */ 
				if (r->argc < (5+has_cand))
					r = pushBit(mb, r, ignore_case);
				if (r->argc < (6+has_cand))
					r = pushBit(mb, r, anti);
				freeInstruction(p);
				p = r;
				actions++;
			}
		}

		/* inject table ids into subselect 
		 * s = subselect(c, C1..) => subselect(c, t, C1..)
		 */
		if (isSubSelect(p) && p->retc == 1) { 
			int tid = 0;

			if ((tid = subselect_find_tids(&subselects, getArg(p, 0))) >= 0) {
				int lastbat = lastbat_arg(mb, p);
				if (getArgType(mb, p, lastbat) == TYPE_bat) /* empty candidate list bat_nil */
					getArg(p, lastbat) = tid;
				else
					p = PushArgument(mb, p, tid, lastbat+1);
				/* make sure to resolve again */
				p->token = ASSIGNsymbol; 
				p->typechk = TYPE_UNKNOWN;
        			p->fcn = NULL;
        			p->blk = NULL;
				actions++;
			}
		}
		else if ( (GDKdebug & (1<<15)) &&
			 isMatJoinOp(p) && p->retc == 2
			 && !(getFunctionId(p) == joinRef && p->argc > 4)
			 ) { 
			int ltid = 0, rtid = 0, done = 0;
			int range = 0;

			if(getFunctionId(p) == joinRef)
				range = (p->argc >= 4);

			if ((ltid = subselect_find_tids(&subselects, getArg(p, 0))) >= 0 && 
			    (rtid = subselect_find_tids(&subselects, getArg(p, 1))) >= 0) {
				p = PushArgument(mb, p, ltid, 4+range);
				p = PushArgument(mb, p, rtid, 5+range);
				done = 1;
			} else if ((ltid = subselect_find_tids(&subselects, getArg(p, 0))) >= 0) { 
				p = PushArgument(mb, p, ltid, 4+range);
				p = PushNil(mb, p, 5+range, TYPE_bat); 
				done = 1;
			} else if ((rtid = subselect_find_tids(&subselects, getArg(p, 1))) >= 0) {
				p = PushNil(mb, p, 4+range, TYPE_bat); 
				p = PushArgument(mb, p, rtid, 5+range);
				done = 1;
			}
			if (done) {
				if(getFunctionId(p) == antijoinRef)
					p = pushInt(mb, p, JOIN_NE); 
				p = pushBit(mb, p, FALSE); /* do not match nils */
				p = pushNil(mb, p, TYPE_lng); /* no estimate */

				/* TODO join* -> subjoin* */
				if(getFunctionId(p) == joinRef)
					getFunctionId(p) = subjoinRef;
				else if(getFunctionId(p) == antijoinRef)
					getFunctionId(p) = subthetajoinRef;
				else if(getFunctionId(p) == thetajoinRef)
					getFunctionId(p) = subthetajoinRef;
				else if(getFunctionId(p) == bandjoinRef)
					getFunctionId(p) = subbandjoinRef;
				/* make sure to resolve again */
				p->token = ASSIGNsymbol; 
				p->typechk = TYPE_UNKNOWN;
        			p->fcn = NULL;
        			p->blk = NULL;
				actions++;
			}
		}
		/* Leftfetchjoins involving rewriten table ids need to be flattend
		 * l = leftfetchjoin(t, c); => l = c;
		 * and
		 * l = leftfetchjoin(s, ntids); => l = s;
		 */
		else if (getModuleId(p) == algebraRef && getFunctionId(p) == leftfetchjoinRef) {
			int var = getArg(p, 1);
			
			if (subselect_find_subselect(&subselects, var) > 0) {
				InstrPtr q = newAssignment(mb);

				getArg(q, 0) = getArg(p, 0); 
				(void) pushArgument(mb, q, getArg(p, 2));
				actions++;
				freeInstruction(p);
				continue;
			} else { /* deletes/updates use table ids */
				int var = getArg(p, 2);
				InstrPtr q = mb->stmt[vars[var]]; /* BEWARE: the optimizer may not add or remove statements ! */

				if (q->token == ASSIGNsymbol) {
					var = getArg(q, 1);
					q = mb->stmt[vars[var]]; 
				}
				if (subselect_find_subselect(&subselects, var) > 0) {
					InstrPtr qq = newAssignment(mb);
					/* TODO: check result */

					getArg(qq, 0) = getArg(p, 0); 
					(void) pushArgument(mb, qq, getArg(p, 1));
					actions++;
					freeInstruction(p);
					continue;
				}
				/* c = sql.delta(b,uid,uval,ins);
		 		 * l = leftfetchjoin(x, c); 
		 		 * into
		 		 * l = sql.projectdelta(x,b,uid,uval,ins);
		 		 */
				else if (getModuleId(q) == sqlRef && getFunctionId(q) == deltaRef && q->argc == 5) {
					q = copyInstruction(q);
					setFunctionId(q, projectdeltaRef);
					getArg(q, 0) = getArg(p, 0); 
					q = PushArgument(mb, q, getArg(p, 1), 1);
					freeInstruction(p);
					p = q;
					actions++;
				}
			}
		}
		pushInstruction(mb,p);
	}
	for (; i<limit; i++) 
		if (old[i])
			pushInstruction(mb,old[i]);
	for (; i<slimit; i++) 
		if (old[i])
			freeInstruction(old[i]);
	GDKfree(old);
	if (!push_down_delta) {
		GDKfree(vars);
		return actions;
	}

	/* now push selects through delta's */
	limit = mb->stop;
	slimit= mb->ssize;
	old = mb->stmt;

	if (newMalBlkStmt(mb, mb->stop+(5*push_down_delta)) <0 ) {
		mb->stmt = old;
		GDKfree(vars);
		return actions;

	}
	pushInstruction(mb,old[0]);

	for (i = 1; i < limit; i++) {
		int lastbat;
		p = old[i];

		for (j = 0; j<p->retc; j++) {
 			int res = getArg(p, j);
			vars[res] = i;
		}

		/* push subslice under projectdelta */
		if (isSlice(p) && p->retc == 1) {
			int var = getArg(p, 1);
			InstrPtr q = old[vars[var]];
			if (getModuleId(q) == sqlRef && getFunctionId(q) == projectdeltaRef) {
				InstrPtr r = copyInstruction(p);
				InstrPtr s = copyInstruction(q);
				ValRecord cst;

				/* slice the candidates */
				setFunctionId(r, sliceRef);
				getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid, TYPE_oid));
				getArg(r, 1) = getArg(s, 1); 
				cst.vtype = getArgType(mb, r, 2);
				cst.val.wval = 0;
				getArg(r, 2) = defConstant(mb, cst.vtype, &cst); /* start from zero */
				pushInstruction(mb,r);

				/* dummy result for the old q, will be removed by deadcode optimizer */
				getArg(q, 0) = newTmpVariable(mb, getArgType(mb, q, 0));

				getArg(s, 1) = getArg(r, 0); /* use result of subslice */
				pushInstruction(mb, s);
			}
		}
		/* c = delta(b, uid, uvl, ins)
		 * s = subselect(c, C1..)
		 *
		 * nc = subselect(b, C1..)
		 * ni = subselect(ins, C1..)
		 * nu = subselect(uvl, C1..)
		 * s = subdelta(nc, uid, nu, ni);
		 *
		 * doesn't handle Xsubselect(x, .. z, C1.. cases) ie multicolumn selects
		 */
		lastbat = lastbat_arg(mb, p);
		if (isSubSelect(p) && p->retc == 1 && lastbat == 2) {
			int var = getArg(p, 1);
			InstrPtr q = old[vars[var]];

			if (q->token == ASSIGNsymbol) {
				var = getArg(q, 1);
				q = old[vars[var]]; 
			}
			if (getModuleId(q) == sqlRef && getFunctionId(q) == deltaRef) {
				InstrPtr r = copyInstruction(p);
				InstrPtr s = copyInstruction(p);
				InstrPtr t = copyInstruction(p);
				InstrPtr u = copyInstruction(q);
		
				getArg(r, 0) = newTmpVariable(mb, newBatType(TYPE_oid, TYPE_oid));
				getArg(r, 1) = getArg(q, 1); /* column */
				pushInstruction(mb,r);
				getArg(s, 0) = newTmpVariable(mb, newBatType(TYPE_oid, TYPE_oid));
				getArg(s, 1) = getArg(q, 3); /* updates */
				s = ReplaceWithNil(mb, s, 2, TYPE_bat); /* no candidate list */
				setArgType(mb, s, 2, newBatType(TYPE_oid,TYPE_oid));
				/* make sure to resolve again */
				s->token = ASSIGNsymbol; 
				s->typechk = TYPE_UNKNOWN;
        			s->fcn = NULL;
        			s->blk = NULL;
				pushInstruction(mb,s);
				getArg(t, 0) = newTmpVariable(mb, newBatType(TYPE_oid, TYPE_oid));
				getArg(t, 1) = getArg(q, 4); /* inserts */
				pushInstruction(mb,t);

				setFunctionId(u, subdeltaRef);
				getArg(u, 0) = getArg(p,0);
				getArg(u, 1) = getArg(r,0);
				getArg(u, 2) = getArg(p,2); /* pre-cands */
				getArg(u, 3) = getArg(q,2); /* update ids */
				getArg(u, 4) = getArg(s,0);
				u = pushArgument(mb, u, getArg(t,0));
				pushInstruction(mb,u);	
				freeInstruction(p);
				continue;
			}
		}
		pushInstruction(mb,p);
	}
	for (; i<limit; i++) 
		if (old[i])
			pushInstruction(mb,old[i]);
	GDKfree(vars);
	GDKfree(old);
	return actions;
}
Ejemplo n.º 21
0
int
OPTaccumulatorsImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i, limit,slimit;
	InstrPtr p,q;
	Module scope = cntxt->nspace;
	int actions = 0;
	InstrPtr *old;
	Lifespan span;

	(void) pci;
	(void) stk;		/* to fool compilers */
	span = setLifespan(mb);
	if( span == NULL)
		return 0;
	old= mb->stmt;
	limit= mb->stop;
	slimit= mb->ssize;
	if ( newMalBlkStmt(mb,mb->stop) < 0){
		GDKfree(span);
		return 0;
	}
	for (i = 0; i < limit; i++) {
		p = old[i];

		if( getModuleId(p) != batcalcRef ) {
			pushInstruction(mb,p);
			continue;
		}
		OPTDEBUGaccumulators
			printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL);
		if (p->retc==1 && p->argc == 2) {
			/* unary operation, avoid clash with binary */
			pushInstruction(mb,p);
			continue;
		}
		if( getLastUpdate(span,getArg(p,0)) != i ) {
			/* only consider the last update to this variable */
			pushInstruction(mb,p);
			continue;
		}

		if (p->retc==1  && p->argc == 3 && isaBatType(getArgType(mb,p,0))) {
			int b1 =getEndLifespan(span,getArg(p,1))<=i && getArgType(mb,p,1) == getArgType(mb,p,0);
			int b2 =getEndLifespan(span,getArg(p,2))<=i && getArgType(mb,p,2) == getArgType(mb,p,0) ;
			if ( b1 == 0 && b2 == 0){
				pushInstruction(mb,p);
				continue;
			}
			/* binary/unary operation, check arguments for being candidates */
			q= copyInstruction(p);
			p= pushBit(mb,p, b1);
			p= pushBit(mb,p, b2);

			typeChecker(cntxt->fdout, scope, mb, p, TRUE);
			if (mb->errors || p->typechk == TYPE_UNKNOWN) {
				OPTDEBUGaccumulators{
					mnstr_printf(cntxt->fdout,"# Failed typecheck");
					printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL);
				}
				/* reset instruction error buffer */
				cntxt->errbuf[0]=0;
				mb->errors = 0;
				freeInstruction(p);
				p=q; /* restore */
			} else  {