Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/*
 * The trace operation collects the events in the BATs
 * and creates a secondary result set upon termination
 * of the query. 
 */
static void
SQLsetTrace(backend *be, Client cntxt, bit onoff)
{
	InstrPtr q, resultset;
	InstrPtr tbls, cols, types, clen, scale;
	MalBlkPtr mb = cntxt->curprg->def;
	int k;

	(void) be;
	if (onoff) {
		(void) newStmt(mb, "profiler", "start");
		initTrace();
	} else {
		(void) newStmt(mb, "profiler", "stop");
		/* cook a new resultSet instruction */
		resultset = newInstruction(mb,ASSIGNsymbol);
		setModuleId(resultset, sqlRef);
		setFunctionId(resultset, resultSetRef);
	    getArg(resultset,0)= newTmpVariable(mb,TYPE_int);


		/* build table defs */
		tbls = newStmt(mb,batRef, newRef);
		setVarType(mb, getArg(tbls,0), newBatType(TYPE_oid, TYPE_str));
		tbls = pushType(mb, tbls, TYPE_oid);
		tbls = pushType(mb, tbls, TYPE_str);
		resultset= pushArgument(mb,resultset, getArg(tbls,0));

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q,getArg(tbls,0));
		q= pushStr(mb,q,".trace");
		k= getArg(q,0);

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q,k);
		q= pushStr(mb,q,".trace");

		/* build colum defs */
		cols = newStmt(mb,batRef, newRef);
		setVarType(mb, getArg(cols,0), newBatType(TYPE_oid, TYPE_str));
		cols = pushType(mb, cols, TYPE_oid);
		cols = pushType(mb, cols, TYPE_str);
		resultset= pushArgument(mb,resultset, getArg(cols,0));

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q,getArg(cols,0));
		q= pushStr(mb,q,"usec");
		k= getArg(q,0);

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q, getArg(cols,0));
		q= pushStr(mb,q,"statement");

		/* build type defs */
		types = newStmt(mb,batRef, newRef);
		setVarType(mb, getArg(types,0), newBatType(TYPE_oid, TYPE_str));
		types = pushType(mb, types, TYPE_oid);
		types = pushType(mb, types, TYPE_str);
		resultset= pushArgument(mb,resultset, getArg(types,0));

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q, getArg(types,0));
		q= pushStr(mb,q,"bigint");
		k= getArg(q,0);

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q, k);
		q= pushStr(mb,q,"clob");

		/* build scale defs */
		clen = newStmt(mb,batRef, newRef);
		setVarType(mb, getArg(clen,0), newBatType(TYPE_oid, TYPE_int));
		clen = pushType(mb, clen, TYPE_oid);
		clen = pushType(mb, clen, TYPE_int);
		resultset= pushArgument(mb,resultset, getArg(clen,0));

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q, getArg(clen,0));
		q= pushInt(mb,q,64);
		k= getArg(q,0);

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q, k);
		q= pushInt(mb,q,0);

		/* build scale defs */
		scale = newStmt(mb,batRef, newRef);
		setVarType(mb, getArg(scale,0), newBatType(TYPE_oid, TYPE_int));
		scale = pushType(mb, scale, TYPE_oid);
		scale = pushType(mb, scale, TYPE_int);
		resultset= pushArgument(mb,resultset, getArg(scale,0));

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb,q, getArg(scale,0));
		q= pushInt(mb,q,0);
		k= getArg(q,0);

		q= newStmt(mb,batRef,appendRef);
		q= pushArgument(mb, q, k);
		q= pushInt(mb,q,0);

		/* add the ticks column */

		q = newStmt(mb, profilerRef, "getTrace");
		q = pushStr(mb, q, putName("usec",4));
		resultset= pushArgument(mb,resultset, getArg(q,0));

		/* add the stmt column */
		q = newStmt(mb, profilerRef, "getTrace");
		q = pushStr(mb, q, putName("stmt",4));
		resultset= pushArgument(mb,resultset, getArg(q,0));

		pushInstruction(mb,resultset);
	}
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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;
}