Пример #1
0
static int
OPTallConstant(Client cntxt, MalBlkPtr mb, InstrPtr p)
{
	int i;
	(void)cntxt;

	if ( !(p->token == ASSIGNsymbol ||
		   getModuleId(p) == calcRef ||
		   getModuleId(p) == strRef ||
		   getModuleId(p) == mtimeRef ||
		   getModuleId(p) == mmathRef))
		return FALSE;
	if (getModuleId(p) == mmathRef && strcmp(getFunctionId(p), "rand") == 0)
		return FALSE;

	for (i = p->retc; i < p->argc; i++)
		if (isVarConstant(mb, getArg(p, i)) == FALSE)
			return FALSE;
	for (i = 0; i < p->retc; i++) {
		if (isaBatType(getArgType(mb, p, i)))
			return FALSE;
		if ( mb->unsafeProp ) 
			return FALSE;
	}
	return TRUE;
}
Пример #2
0
/*
 * Removal of elements from the symbol table should be
 * done with care. For, it should be assured that
 * there are no references to the definition at the
 * moment of removal. This situation can not easily
 * checked at runtime, without tremendous overhead.
 */
void deleteSymbol(Module scope, Symbol prg){
	InstrPtr sig;
	int t;

	sig = getSignature(prg);
#ifdef _DEBUG_MODULE_
	fprintf(stderr,"#delete symbol %s.%s from %s\n", getModuleId(sig), getFunctionId(sig), prg->name);
#endif
	if (getModuleId(sig) && getModuleId(sig)!= scope->name ){
		/* move the definition to the proper place */
		/* default scope is the last resort */
		Module c= findModule(scope, getModuleId(sig));
		if(c )
			scope = c;
	}
	t = getSymbolIndex(getFunctionId(sig));
	if (scope->space[t] == prg) {
		scope->space[t] = scope->space[t]->peer;
		freeSymbol(prg);
	} else {
		Symbol nxt = scope->space[t];
		while (nxt->peer != NULL) {
			if (nxt->peer == prg) {
				nxt->peer = prg->peer;
				nxt->skip = prg->peer;
				freeSymbol(prg);
				return;
			}
			nxt = nxt->peer;
		}
	}
}
Пример #3
0
/*
 * For clarity we show the last optimizer applied
 * also as the last of the list, although it is linked with mb.
*/
void showMalBlkHistory(stream *out, MalBlkPtr mb)
{
	MalBlkPtr m=mb;
	InstrPtr p,sig;
	int j=0;
	str msg;

	sig = getInstrPtr(mb,0);
	m= m->history;
	while(m){
		p= getInstrPtr(m,m->stop-1);
		if( p->token == REMsymbol){
			msg= instruction2str(m, 0, p, FALSE);
			if (msg ) {
				mnstr_printf(out,"%s.%s[%2d] %s\n", 
					getModuleId(sig), getFunctionId(sig),j++,msg+3);
				GDKfree(msg);
			}
		} 
		m= m->history;
	}
	p=getInstrPtr(mb,mb->stop-1);
	if( p->token == REMsymbol){
		msg= instruction2str(mb, 0, p, FALSE);
		if (msg) {
			mnstr_printf(out,"%s.%s[%2d] %s\n", 
				getModuleId(sig), getFunctionId(sig),j++,msg+3);
				GDKfree(msg);
		}
	}
}
Пример #4
0
static int
malMatch(InstrPtr p1, InstrPtr p2)
{
	int i, j;

	if (getFunctionId(p1) == 0 && getFunctionId(p2) != 0)
		return 0;
	if (getModuleId(p1) == 0 && getModuleId(p2) != 0)
		return 0;
	if (getModuleId(p1) != getModuleId(p2))
		return 0;
	if (getFunctionId(p2) == 0)
		return 0;
	if (getFunctionId(p1) != getFunctionId(p2))
		return 0;
	if (p1->retc != p2->retc)
		return 0;
	if (p1->argc != p2->argc)
		return 0;
	if (p1->barrier != p2->barrier)
		return 0;
	for (i = 0; i < p1->argc; i++)
		for (j = i + 1; j < p1->argc; j++)
			if ((getArg(p1, i) == getArg(p1, j)) != (getArg(p2, i) == getArg(p2, j)))
				return 0;
	return 1;
}
Пример #5
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);
			}
		} 
Пример #6
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;
}
Пример #7
0
int
OPTinlineImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
{
    int i;
    InstrPtr q,sig;
    int actions = 0;

    (void) p;
    (void)stk;

    for (i = 1; i < mb->stop; i++) {
        q = getInstrPtr(mb, i);
        if( q->blk ) {
            sig = getInstrPtr(q->blk,0);
            /*
             * Time for inlining functions that are used in multiplex operations.
             * They are produced by SQL compiler.
             */
            if( getFunctionId(q)== multiplexRef &&
                    getModuleId(q) == malRef &&
                    OPTinlineMultiplex(cntxt,mb,q)) {

                OPTDEBUGinline {
                    mnstr_printf(cntxt->fdout,"#multiplex inline function\n");
                    printInstruction(cntxt->fdout,mb,0,q,LIST_MAL_ALL);
                }

                varSetProp(mb, getArg(q,0), inlineProp, op_eq, NULL);
            } else
                /*
                 * Check if the function definition is tagged as being inlined.
                 */
                if (sig->token == FUNCTIONsymbol &&
Пример #8
0
/*
 * After filling in a structure it is added to the multi-level symbol
 * table.  We keep a skip list of similarly named function symbols.
 * This speeds up searching provided the modules adhere to the
 * structure and group the functions as well.
 */
void insertSymbol(Module scope, Symbol prg){
	InstrPtr sig;
	int t;
	Module c;

	assert(scope);
	sig = getSignature(prg);
#ifdef _DEBUG_MODULE_
	fprintf(stderr,"#insertSymbol: %s.%s in %s ", getModuleId(sig), getFunctionId(sig), scope->name);
#endif
	if(getModuleId(sig) && getModuleId(sig)!= scope->name){
		/* move the definition to the proper place */
		/* default scope is the last resort */
		c= findModule(scope,getModuleId(sig));
		if ( c )
			scope = c;
#ifdef _DEBUG_MODULE_
	fprintf(stderr," found alternative module %s ", scope->name);
#endif
	}
	t = getSymbolIndex(getFunctionId(sig));
	if( scope->space == NULL) {
		scope->space = (Symbol *) GDKzalloc(MAXSCOPE * sizeof(Symbol));
		if (scope->space == NULL)
			return;
	}
	assert(scope->space);
	if (scope->space[t] == prg){
		/* already known, last inserted */
#ifdef _DEBUG_MODULE_
	fprintf(stderr," unexpected double insert  ");
#endif
	} else {
		prg->peer= scope->space[t];
		scope->space[t] = prg;
		if( prg->peer &&
			idcmp(prg->name,prg->peer->name) == 0)
			prg->skip = prg->peer->skip;
		else
			prg->skip = prg->peer;
	}
	assert(prg != prg->peer);
#ifdef _DEBUG_MODULE_
	fprintf(stderr,"\n");
#endif
}
Пример #9
0
static int
OPTallConstant(Client cntxt, MalBlkPtr mb, InstrPtr p)
{
	int i;
	(void)cntxt;

	if ( !( p->token == ASSIGNsymbol ||
			getModuleId(p) == calcRef ||
		   getModuleId(p) == strRef ||
		   getModuleId(p) == mmathRef ))
		return FALSE;

	for (i = p->retc; i < p->argc; i++)
		if (isVarConstant(mb, getArg(p, i)) == FALSE)
			return FALSE;
	for (i = 0; i < p->retc; i++)
		if (isaBatType(getArgType(mb, p, i)))
			return FALSE;
	return p->argc != p->retc;
}
Пример #10
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;
}
Пример #11
0
static lng 
SQLgetSpace(mvc *m, MalBlkPtr mb)
{
	sql_trans *tr = m->session->tr;
	lng space = 0, i; 

	for (i = 0; i < mb->stop; i++) {
		InstrPtr p = mb->stmt[i];
		char *f = getFunctionId(p);

		if (getModuleId(p) == sqlRef && (f == bindRef || f == bindidxRef)) {
			int upd = (p->argc == 7 || p->argc == 9), mode = 0;
			char *sname = getVarConstant(mb, getArg(p, 2 + upd)).val.sval;
			char *tname = getVarConstant(mb, getArg(p, 3 + upd)).val.sval;
			char *cname = NULL;
			sql_schema *s = mvc_bind_schema(m, sname);

			if (!s || strcmp(s->base.name, dt_schema) == 0) 
				continue;
			cname = getVarConstant(mb, getArg(p, 4 + upd)).val.sval;
			mode = getVarConstant(mb, getArg(p, 5 + upd)).val.ival;
			if (mode != 0 || !cname || !s)
				continue;
			if (f == bindidxRef) {
				sql_idx *i = mvc_bind_idx(m, s, cname);

				if (i && (!isRemote(i->t) && !isMergeTable(i->t))) {
					BAT *b = store_funcs.bind_idx(tr, i, RDONLY);
					if (b) {
						space += getBatSpace(b);
						BBPunfix(b->batCacheid);
					}
				}
			} else if (f == bindRef) {
				sql_table *t = mvc_bind_table(m, s, tname);
				sql_column *c = mvc_bind_column(m, t, cname);

				if (c && (!isRemote(c->t) && !isMergeTable(c->t))) {
					BAT *b = store_funcs.bind_col(tr, c, RDONLY);
					if (b) {
						space += getBatSpace(b);
						BBPunfix(b->batCacheid);
					}
				}
			}
		}
	}
	return space;
}
Пример #12
0
ATerm get_moduleid(int cid, ATerm sid) {
  EM_Session session;
  EM_ModuleId moduleId;

  session = getSession(sid);
  if (session == NULL) {
    return sndValue(ATmake("no-such-session"));
  }

  moduleId = getModuleId(sid);
  if (moduleId == NULL) {
    return sndValue(ATmake("session-not-bound"));
  }
  else {
    return sndValue(ATmake("moduleid(<term>)", moduleId));
  }
}
Пример #13
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;
}
Пример #14
0
ATerm bind_session(int cid, ATerm sid, ATerm moduleId) {
  assert(sid != NULL);
  assert(moduleId != NULL);

  if (getSession(sid) == NULL) {
    return sndValue(ATmake("no-such-session"));
  }
  else {
    EM_ModuleId id = getModuleId(sid);
    EM_ModuleId module = EM_ModuleIdFromTerm(moduleId);
    if (id != NULL && EM_isEqualModuleId(module, id) != 0) {
      ATabort("editor-manager:bind_session: attempt to rebind %t (%t)\n",
	      sid, moduleId);
    }
    putModuleId(sid, module);

    return sndValue(ATmake("session-bound"));
  }
}
Пример #15
0
static void
propagateNonTarget(MalBlkPtr mb, int pc)
{
	int i;
	InstrPtr p;
	str scheduler = putName("scheduler", 9);

	for (; pc < mb->stop; pc++) {
		p = getInstrPtr(mb, pc);
		if (getModuleId(p) == scheduler)
			continue;
		for (i = 0; i < p->argc; i++)
			if (isVarDisabled(mb, getArg(p, i)) && p->token >= 0)
				p->token = -p->token;  /* temporary NOOP */
		if (p->token < 0)
			for (i = 0; i < p->retc; i++)
				setVarDisabled(mb, getArg(p, i));
	}
}
Пример #16
0
static int
isNewSource(InstrPtr p) {
	str mp= getModuleId(p);
	if( mp == sqlRef && getFunctionId(p) == bindRef) return 1;
	if( mp == calcRef) return 1;
	if( mp == batcalcRef) return 1;
	if( mp == strRef) return 1;
	if( mp == batstrRef) return 1;
	if( mp == putName("array",5)) return 1;
	if( mp == putName("url",3)) return 1;
	if( mp == putName("daytime",7)) return 1;
	if( mp == putName("day",3)) return 1;
	if( mp == putName("date",4)) return 1;
	if( mp == putName("time",4)) return 1;
	if( mp == putName("tzone",5)) return 1;
	if( mp == putName("color",4)) return 1;
	if( mp == putName("batcolor",8)) return 1;
	if( mp == putName("blob",4)) return 1;
	return 0;
}
Пример #17
0
/*
 * The multiplexSimple is called by the MAL scenario. It bypasses
 * the optimizer infrastructure, to avoid excessive space allocation
 * and interpretation overhead.
 */
str
OPTmultiplexSimple(Client cntxt)
{
	MalBlkPtr mb= cntxt->curprg->def;
	int i, doit=0;
	InstrPtr p;
	if(mb)
	for( i=0; i<mb->stop; i++){
		p= getInstrPtr(mb,i);
		if(getModuleId(p) == malRef && getFunctionId(p) == multiplexRef)
			doit++;
	}
	if( doit) {
		OPTmultiplexImplementation(cntxt, mb, 0, 0);
		chkTypes(cntxt->fdout, cntxt->nspace, mb,TRUE);
		if ( mb->errors == 0) {
			chkFlow(cntxt->fdout, mb);
			chkDeclarations(cntxt->fdout,mb);
		}
	}
	return 0;
}
Пример #18
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;
}
Пример #19
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;
}
Пример #20
0
int malAtomProperty(MalBlkPtr mb, InstrPtr pci)
{
	str name;
	int tpe;
	(void)mb;  /* fool compilers */
	assert(pci != 0);
	name = getFunctionId(pci);
	tpe = getTypeIndex(getModuleId(pci), (int)strlen(getModuleId(pci)), TYPE_any);
	if (tpe < 0 || tpe >= GDKatomcnt || tpe >= MAXATOMS)
		return 0;
	assert(pci->fcn != NULL);
	switch (name[0]) {
	case 'd':
		if (idcmp("del", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomDel = (void (*)(Heap *, var_t *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'c':
		if (idcmp("cmp", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomCmp = (int (*)(const void *, const void *))pci->fcn;
			BATatoms[tpe].linear = 1;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'f':
		if (idcmp("fromstr", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomFromStr = (int (*)(const char *, int *, ptr *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		if (idcmp("fix", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomFix = (int (*)(const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'h':
		if (idcmp("heap", name) == 0 && pci->argc == 1) {
			/* heap function makes an atom varsized */
			BATatoms[tpe].size = sizeof(var_t);
			assert_shift_width(ATOMelmshift(ATOMsize(tpe)), ATOMsize(tpe));
			BATatoms[tpe].align = sizeof(var_t);
			BATatoms[tpe].atomHeap = (void (*)(Heap *, size_t))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		if (idcmp("hash", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomHash = (BUN (*)(const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'l':
		if (idcmp("length", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomLen = (int (*)(const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'n':
		if (idcmp("null", name) == 0 && pci->argc == 1) {
			ptr atmnull = ((ptr (*)(void))pci->fcn)();

			BATatoms[tpe].atomNull = atmnull;
			setAtomName(pci);
			return 1;
		}
		if (idcmp("nequal", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomCmp = (int (*)(const void *, const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'p':
		if (idcmp("put", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomPut = (var_t (*)(Heap *, var_t *, const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 's':
		if (idcmp("storage", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].storage = (*(int (*)(void))pci->fcn)();
			setAtomName(pci);
			return 1;
		}
		break;
	case 't':
		if (idcmp("tostr", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomToStr = (int (*)(str *, int *, const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'u':
		if (idcmp("unfix", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomUnfix = (int (*)(const void *))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'r':
		if (idcmp("read", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomRead = (void *(*)(void *, stream *, size_t))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	case 'w':
		if (idcmp("write", name) == 0 && pci->argc == 1) {
			BATatoms[tpe].atomWrite = (gdk_return (*)(const void *, stream *, size_t))pci->fcn;
			setAtomName(pci);
			return 1;
		}
		break;
	}
	return 0;
}
Пример #21
0
str
shortStmtRendering(MalBlkPtr mb, MalStkPtr stk,  InstrPtr p)
{
	int i;
	str base, s, t, nme;
	size_t len=  (mb->stop < 1000? 1000: mb->stop) * 128 /* max realistic line length estimate */;

	base = s = GDKmalloc(len);
	if ( s == NULL)
		return s;
	*s =0;
	t=s;
	if (p->token == REMsymbol && !( getModuleId(p) && strcmp(getModuleId(p),"querylog") == 0  && getFunctionId(p) && strcmp(getFunctionId(p),"define") == 0)) 
		return base;
	if (p->barrier == LEAVEsymbol || 
		p->barrier == REDOsymbol || 
		p->barrier == RETURNsymbol || 
		p->barrier == YIELDsymbol || 
		p->barrier == EXITsymbol || 
		p->barrier == RAISEsymbol) {
			snprintf(t,(len-(t-base)), "%s ", operatorName(p->barrier));
			advance(t,base,len);
		}
	if( p->token == FUNCTIONsymbol) {
			snprintf(t,(len-(t-base)), "function %s.", getModuleId(p));
			advance(t,base,len);
		}
	if (p->token == ENDsymbol ){
		snprintf(t,(len-(t-base)), "end %s.%s", getModuleId(getInstrPtr(mb,0)), getFunctionId(getInstrPtr(mb,0)));
		return base;
	}
	// handle the result variables
	for (i = 0; i < p->retc; i++)
		if ( !isTmpVar(mb,getArg(p,i)) || isVarUsed(mb, getArg(p, i)) || isVarUDFtype(mb,getArg(p,i)))
			break;

	if (i == p->retc) // no result arguments
		goto short_end;

	/* display optional multi-assignment list */
	if( getArgType(mb,p,0) != TYPE_void){
		if (p->retc > 1 && t < base + len-1){
			*t++ = '(';
			*t=0;
		}

		for (i = 0; i < p->retc; i++) {
			nme = shortRenderingTerm(mb, stk, p,i);
			snprintf(t,(len-(t-base)), "%s%s", (i?", ":""), nme);
			GDKfree(nme);
			advance(t,base,len);
		}
		if (p->retc > 1 && t< base+len)
			*t++ = ')';
		if( t < base +len) *t++ = ':';
		if( t < base +len) *t++ = '=';
		if( t < base +len) *t++ = ' ';
	}
	*t =0;

	short_end:
	advance(t,base,len);

	// handle the instruction mapping
	snprintf(t,  (len-(t-base)),"%s", (getFunctionId(p)?getFunctionId(p):""));
	advance(t,base,len);

	// handle the arguments, constants should  be shown including their non-default type
	/* display optional multi-assignment list */
	if( t< base + len) *t++ = '(';
	for (i = p->retc; i < p->argc; i++) {
		nme = shortRenderingTerm(mb, stk, p,i);
		snprintf(t,(len-(t-base)), "%s%s", (i!= p->retc? ", ":" "), nme);
		GDKfree(nme);
		advance(t,base,len);
		if (i < p->retc - 1 && t < base+len){
			*t++ = ',';
			*t++ = ' ';
		}
	}
	if( t < base + len) *t++ = ' ';
	if( t < base + len) *t++ = ')';
	*t=0;

	if (t >= s + len)
		throw(MAL,"instruction2str:","instruction too long");
	return base;
}
Пример #22
0
str
instruction2str(MalBlkPtr mb, MalStkPtr stk,  InstrPtr p, int flg)
{
	int i;
	str base, t;
	size_t len = 512 + (p->argc * 128);		 /* max realistic line length estimate */
	str arg;

	t = base = GDKmalloc(len);
	if ( base == NULL)
		return NULL;
	if (!flg) {
		*t++ = '#';
		len--;
		if (p->typechk == TYPE_UNKNOWN) {
			*t++ = '!';	/* error */
			len--;
		}
	}
	*t = 0;
	if (p->token == REMsymbol && !( getModuleId(p) && strcmp(getModuleId(p),"querylog") == 0  && getFunctionId(p) && strcmp(getFunctionId(p),"define") == 0)) {
		/* do nothing */
	} else if (p->barrier) {
		if (p->barrier == LEAVEsymbol ||
			p->barrier == REDOsymbol ||
			p->barrier == RETURNsymbol ||
			p->barrier == YIELDsymbol ||
			p->barrier == RAISEsymbol) {
			if (!copystring(&t, "    ", &len))
				return base;
		}
		arg = operatorName(p->barrier);
		if (!copystring(&t, arg, &len) ||
			!copystring(&t, " ", &len))
			return base;
	} else if( functionStart(p) && flg != LIST_MAL_CALL ){
		return fcnDefinition(mb, p, t, flg, base, len + (t - base));
	} else if (!functionExit(p) && flg!=LIST_MAL_CALL) {
		// beautify with tabs
		if (!copystring(&t, "    ", &len))
			return base;
	}
	switch (p->token<0?-p->token:p->token) {
	case FCNcall:
	case FACcall:
	case PATcall:
	case CMDcall:
	case ASSIGNsymbol :
		// is any variable explicit or used
		for (i = 0; i < p->retc; i++)
			if ( !isTmpVar(mb,getArg(p,i)) || isVarUsed(mb, getArg(p, i)) || isVarUDFtype(mb,getArg(p,i)))
				break;

		if (i == p->retc)
			break;

		/* display multi-assignment list */
		if (p->retc > 1 && !copystring(&t, "(", &len))
			return base;

		for (i = 0; i < p->retc; i++) {
			arg= renderTerm(mb, stk, p, i, flg);
			if (arg) {
				if (!copystring(&t, arg, &len)) {
					GDKfree(arg);
					return base;
				}
				GDKfree(arg);
			}
			if (i < p->retc - 1 && !copystring(&t, ", ", &len))
				return base;
		}
		if (p->retc > 1 && !copystring(&t, ")", &len))
			return base;

		if (p->argc > p->retc || getFunctionId(p)) {
			if (!copystring(&t, " := ", &len))
				return base;
		}
		break;
	case ENDsymbol:
		if (!copystring(&t, "end ", &len) ||
			!copystring(&t, getModuleId(getInstrPtr(mb,0)), &len) ||
			!copystring(&t, ".", &len) ||
			!copystring(&t, getFunctionId(getInstrPtr(mb, 0)), &len))
			return base;
		break;
	case COMMANDsymbol:
	case FUNCTIONsymbol:
	case FACTORYsymbol:
	case PATTERNsymbol:
		if (flg & LIST_MAL_VALUE) {
			if (!copystring(&t, operatorName(p->token), &len) ||
				!copystring(&t, " ", &len))
				return base;
		}
		return fcnDefinition(mb, p, t, flg, base, len + (t - base));
	case REMsymbol:
	case NOOPsymbol:
		if (!copystring(&t, "#", &len))
			return base;
		if (getVar(mb, getArg(p, 0))->value.val.sval && getVar(mb, getArg(p, 0))->value.len > 0 &&
			!copystring(&t, getVar(mb, getArg(p, 0))->value.val.sval, &len))
			return base;
		if (!copystring(&t, " ", &len))
			return base;
		break;
	default:
		i = snprintf(t, len, " unknown symbol ?%d? ", p->token);
		if (i < 0 || (size_t) i >= len)
			return base;
		len -= (size_t) i;
		t += i;
		break;
	}

	if (getModuleId(p)) {
		if (!copystring(&t, getModuleId(p), &len) ||
			!copystring(&t, ".", &len))
			return base;
	}
	if (getFunctionId(p)) {
		if (!copystring(&t, getFunctionId(p), &len) ||
			!copystring(&t, "(", &len))
			return base;
	} else if (p->argc > p->retc + 1) {
		if (!copystring(&t, "(", &len))
			return base;
	}
	for (i = p->retc; i < p->argc; i++) {
		arg= renderTerm(mb, stk, p, i, flg);
		if (arg) {
			if (!copystring(&t, arg, &len)) {
				GDKfree(arg);
				return base;
			}
			GDKfree(arg);
		}

		if (i < p->argc -1 && !copystring(&t, ", ", &len))
			return base;
	}
	if (getFunctionId(p) || p->argc > p->retc + 1) {
		if (!copystring(&t, ")", &len))
			return base;
	}
	if (p->token != REMsymbol){
		if (!copystring(&t, ";", &len))
			return base;
	}
	return base;
}
Пример #23
0
str
fcnDefinition(MalBlkPtr mb, InstrPtr p, str t, int flg, str base, size_t len)
{
	int i;
	str arg, tpe;

	len -= t - base;
	if (!flg && !copystring(&t, "#", &len))
		return base;
	if( mb->inlineProp && !copystring(&t, "inline ", &len))
		return base;
	if( mb->unsafeProp && !copystring(&t, "unsafe ", &len))
		return base;
	if( mb->sealedProp && !copystring(&t, "sealed ", &len))
		return base;
	if (!copystring(&t, operatorName(p->token), &len) ||
		!copystring(&t, " ", &len) ||
		!copystring(&t, getModuleId(p) ? getModuleId(p) : "user", &len) ||
		!copystring(&t, ".", &len) ||
		!copystring(&t, getFunctionId(p), &len) ||
		!copystring(&t, "(", &len))
		return base;

	for (i = p->retc; i < p->argc; i++) {
		arg = renderTerm(mb, 0, p, i, (LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS));
		if (arg && !copystring(&t, arg, &len)) {
			GDKfree(arg);
			return base;
		}
		GDKfree(arg);
		if( i<p->argc-1 && !copystring(&t, ", ", &len))
			return base;
	}

	advance(t,base,len);
	if (p->varargs & VARARGS && !copystring(&t, "...", &len))
		return base;

	if (p->retc == 1) {
		if (!copystring(&t, "):", &len))
			return base;
		tpe = getTypeName(getVarType(mb, getArg(p,0)));
		if (!copystring(&t, tpe, &len)) {
			GDKfree(tpe);
			return base;
		}
		GDKfree(tpe);
		if (p->varargs & VARRETS && !copystring(&t, "...", &len))
			return base;
	} else {
		if (!copystring(&t, ") (", &len))
			return base;
		for (i = 0; i < p->retc; i++) {
			arg = renderTerm(mb, 0, p, i, (LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS));
			if (arg && !copystring(&t, arg, &len)) {
				GDKfree(arg);
				return base;
			}
			GDKfree(arg);
			if( i<p->retc-1 && !copystring(&t, ", ", &len))
				return base;
		}
		if (p->varargs & VARRETS && !copystring(&t, "...", &len))
			return base;
		if (!copystring(&t, ")", &len))
			return base;
	}

	if (mb->binding[0]) {
		if (!copystring(&t, " address ", &len) ||
			!copystring(&t, mb->binding, &len))
			return base;
	}
	(void) copystring(&t, ";", &len);
	return base;
}
Пример #24
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;
}
Пример #25
0
int
OPTpushrangesImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i,j, limit,actions=0;
	InstrPtr p, *old;
	int x,y,z;
	Range range;

	if( mb->errors) 
		return 0;

	range= (Range) GDKzalloc(mb->vtop * sizeof(RangeRec));
	if (range == NULL)
		return 0;
	OPTDEBUGpushranges
		mnstr_printf(cntxt->fdout,"#Range select optimizer started\n");
	(void) stk;
	(void) pci;
	
	limit = mb->stop;
	old = mb->stmt;
	/*
	 * In phase I we collect information about constants
	 */
	for (i = 0; i < limit; i++) {
		p = old[i];
		if( p->barrier) 
			break; /* end of optimizer */
		for(j=p->retc; j< p->argc; j++)
			range[getArg(p,j)].used++;
		for(j=0; j<p->retc; j++){
			range[getArg(p,j)].lastupdate= i;
			if( range[getArg(p,j)].lastrange == 0)
				range[getArg(p,j)].lastrange= i;
		} 
		if( getModuleId(p)== algebraRef && 
			( getFunctionId(p)== selectRef || getFunctionId(p)== uselectRef) ){
			/*
			 * The operation X:= algebra.select(Y,L,H,Li,Hi) is analysed.
			 * First, we attempt to propagate the range known for Y onto the
			 * requested range of X. This may lead to smaller range of
			 * even the conclusion that X is necessarily empty.
			 * Of course, only under the condition that Y has not been changed by a
			 * side-effect since it was bound to X.
			 */
			x= getArg(p,1);
			y= getArg(p,2);
			if( range[x].lcst && isVarConstant(mb,y) ){
				/* merge lowerbound */
				if( ATOMcmp( getVarGDKType(mb,y), 
						VALptr( &getVarConstant(mb,range[x].lcst)), 
						VALptr( &getVarConstant(mb,y)) ) > 0){
					getArg(p,2)= range[x].lcst;
					z= range[x].srcvar;
					if( getArg(p,1) == x && 
						range[z].lastupdate == range[z].lastrange){
						getArg(p,1) = z;
						actions++;
					}
				}
				y= getArg(p,3);
				/* merge higherbound */
				if( ATOMcmp( getVarGDKType(mb,y), 
						VALptr( &getVarConstant(mb,range[x].hcst)), 
						VALptr( &getVarConstant(mb,y)) ) < 0 ||
					ATOMcmp( getVarGDKType(mb,y),
						VALptr( &getVarConstant(mb,y)),
						 ATOMnilptr(getVarType(mb,y)) ) == 0){
					getArg(p,3)= range[x].hcst;
					z= range[x].srcvar;
					if( getArg(p,1) == x && range[z].lastupdate == range[z].lastrange){
						getArg(p,1) = z;
						actions++;
					}
				}
			}
			/*
			 * The second step is to assign the result of this exercise to the
			 * result variable.
			 */
			x= getArg(p,0);
			if( isVarConstant(mb, getArg(p,2)) ){
				range[x].lcst = getArg(p,2);
				range[x].srcvar= getArg(p,1);
				range[x].lastupdate= range[x].lastrange = i;
			}
			if( isVarConstant(mb, getArg(p,3)) ){
				range[x].hcst = getArg(p,3);
				range[x].srcvar= getArg(p,1);
				range[x].lastupdate= range[x].lastrange = i;
			}
			/*
			 * If both range bounds are constant, we can also detect empty results.
			 * It is empty if L> H or when L=H and the bounds are !(true,true).
			 */
			x= getArg(p,2);
			y= getArg(p,3);
			if( isVarConstant(mb, x)  &&
				isVarConstant(mb, y)  ){
				z =ATOMcmp( getVarGDKType(mb,y),
                        VALptr( &getVarConstant(mb,x)),
                        VALptr( &getVarConstant(mb,y)));
				x=  p->argc > 4;
				x= x && isVarConstant(mb,getArg(p,4));
				x= x && isVarConstant(mb,getArg(p,5));
				x= x && getVarConstant(mb,getArg(p,4)).val.btval;
				x= x && getVarConstant(mb,getArg(p,5)).val.btval;
				if( z > 0 || (z==0 && p->argc>4 && !x)) {
					int var = getArg(p, 0);
					wrd zero = 0;
					ValRecord v, *vp;

					vp = VALset(&v, TYPE_wrd, &zero);
					varSetProp(mb, var, rowsProp, op_eq, vp);
					/* create an empty replacement */
					x = getArgType(mb, p, 1);
					p->argc=1;
					getModuleId(p)= batRef;
					getFunctionId(p)= newRef;
					p= pushArgument(mb,p, newTypeVariable(mb, getHeadType(x)));
					(void) pushArgument(mb,p, newTypeVariable(mb, getTailType(x)));
					actions++;
				}
			}
		}
	}
	OPTDEBUGpushranges
		for(j=0; j< mb->vtop; j++)
		if( range[j].used )
			printRange(cntxt, mb,range,j);
	/*
	 * Phase II, if we succeeded in pushing constants around and
	 * changing instructions, we might as well try once more to perform
	 * aliasRemoval, constantExpression, and pushranges.
	 */
	GDKfree(range);
	return actions;
}
Пример #26
0
static void
SQLgetStatistics(Client cntxt, mvc *m, MalBlkPtr mb)
{
	InstrPtr *old = NULL;
	int oldtop, i, actions = 0, size = 0;
	lng clk = GDKusec();
	sql_trans *tr = m->session->tr;
	str msg;

	old = mb->stmt;
	oldtop = mb->stop;
	size = (mb->stop * 1.2 < mb->ssize) ? mb->ssize : (int) (mb->stop * 1.2);
	mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr));
	mb->ssize = size;
	mb->stop = 0;

	for (i = 0; i < oldtop; i++) {
		InstrPtr p = old[i];
		char *f = getFunctionId(p);
		ValRecord vr;

		if (getModuleId(p) == sqlRef && f == tidRef) {
			char *sname = getVarConstant(mb, getArg(p, 2)).val.sval;
			char *tname = getVarConstant(mb, getArg(p, 3)).val.sval;
			sql_schema *s = mvc_bind_schema(m, sname);
			sql_table *t;

			if (!s || strcmp(s->base.name, dt_schema) == 0) {
				pushInstruction(mb, p);
				continue;
			}

		       	t = mvc_bind_table(m, s, tname);

			if (t && (!isRemote(t) && !isMergeTable(t)) && t->p) {
				int k = getArg(p, 0), mt_member = t->p->base.id;

				varSetProp(mb, k, mtProp, op_eq, VALset(&vr, TYPE_int, &mt_member));
			}
		}
		if (getModuleId(p) == sqlRef && (f == bindRef || f == bindidxRef)) {
			int upd = (p->argc == 7 || p->argc == 9);
			char *sname = getVarConstant(mb, getArg(p, 2 + upd)).val.sval;
			char *tname = getVarConstant(mb, getArg(p, 3 + upd)).val.sval;
			char *cname = NULL;
			int not_null = 0, mt_member = 0;
			wrd rows = 1;	/* default to cope with delta bats */
			int mode = 0;
			int k = getArg(p, 0);
			sql_schema *s = mvc_bind_schema(m, sname);
			BAT *b;

			if (!s || strcmp(s->base.name, dt_schema) == 0) {
				pushInstruction(mb, p);
				continue;
			}
			cname = getVarConstant(mb, getArg(p, 4 + upd)).val.sval;
			mode = getVarConstant(mb, getArg(p, 5 + upd)).val.ival;

			if (s && f == bindidxRef && cname) {
				size_t cnt;
				sql_idx *i = mvc_bind_idx(m, s, cname);

				if (i && (!isRemote(i->t) && !isMergeTable(i->t))) {
					cnt = store_funcs.count_idx(tr, i, 1);
					assert(cnt <= (size_t) GDK_oid_max);
					b = store_funcs.bind_idx(m->session->tr, i, RDONLY);
					if (b) {
						str loc;
						if (b->batPersistence == PERSISTENT && BATlocation(&loc, &b->batCacheid) && loc)
							varSetProp(mb, k, fileProp, op_eq, VALset(&vr, TYPE_str, loc));
						cnt = BATcount(b);
						BBPunfix(b->batCacheid);
					}
					rows = (wrd) cnt;
					if (i->t->p) 
						mt_member = i->t->p->base.id;
				}
			} else if (s && f == bindRef && cname) {
				size_t cnt;
				sql_table *t = mvc_bind_table(m, s, tname);
				sql_column *c = mvc_bind_column(m, t, cname);

				if (c && (!isRemote(c->t) && !isMergeTable(c->t))) {
					not_null = !c->null;

					cnt = store_funcs.count_col(tr, c, 1);
					assert(cnt <= (size_t) GDK_oid_max);
					b = store_funcs.bind_col(m->session->tr, c, RDONLY);
					if (b) {
						str loc;
						if (b->batPersistence == PERSISTENT && BATlocation(&loc, &b->batCacheid) && loc)
							varSetProp(mb, k, fileProp, op_eq, VALset(&vr, TYPE_str, loc));
						cnt = BATcount(b);
						BBPunfix(b->batCacheid);
					}
					rows = (wrd) cnt;
					if (c->t->p) 
						mt_member = c->t->p->base.id;
				}
			}
			if (rows > 1 && mode != RD_INS)
				varSetProp(mb, k, rowsProp, op_eq, VALset(&vr, TYPE_wrd, &rows));
			if (not_null)
				varSetProp(mb, k, notnilProp, op_eq, NULL);
			if (mt_member && mode != RD_INS)
				varSetProp(mb, k, mtProp, op_eq, VALset(&vr, TYPE_int, &mt_member));

			{
				int lowprop = hlbProp, highprop = hubProp;
				/* rows == cnt has been checked above to be <= GDK_oid_max */
				oid low = 0, high = low + (oid) rows;
				pushInstruction(mb, p);

				if (mode == RD_INS) {
					low = high;
					high += 1024 * 1024;
				}
				varSetProp(mb, getArg(p, 0), lowprop, op_gte, VALset(&vr, TYPE_oid, &low));
				varSetProp(mb, getArg(p, 0), highprop, op_lt, VALset(&vr, TYPE_oid, &high));
			}

			if (not_null)
				actions++;
		} else {
			pushInstruction(mb, p);
		}
	}
	GDKfree(old);
	msg = optimizerCheck(cntxt, mb, "optimizer.SQLgetstatistics", actions, GDKusec() - clk);
	if (msg)		/* what to do with an error? */
		GDKfree(msg);
}
Пример #27
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;
}
Пример #28
0
int
OPTstrengthReductionImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i, j = 0, k, se= FALSE;
	InstrPtr p;
	int bk, ik, blk, blkbegin, blkexit, actions = 0;
	InstrPtr *before, *within, *old = mb->stmt;
	Lifespan span;

	(void) cntxt;
	(void) pci;
	(void) stk;		/* to fool compilers */

	before = (InstrPtr *) GDKmalloc((mb->ssize + 1) * sizeof(InstrPtr));
	within = (InstrPtr *) GDKmalloc((mb->ssize + 1) * sizeof(InstrPtr));
	if (before== NULL || within == NULL){
		if(before) GDKfree(before);
		if(within) GDKfree(within);
		return 0;
	}
	bk = 0;
	ik = 0;
	blk = 0;
	blkexit= blkbegin = 0;
	for (i = 0; i < mb->stop; i++)
		before[i] = within[i] = 0;
	before[bk++] = getInstrPtr(mb, 0);

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

	for (i = 1; i < mb->stop - 1; i++) {
		p = getInstrPtr(mb, i);
		if (blockStart(p)) {
			if (blkbegin == 0){
				if( isLoopBarrier(mb,i) ){
					blkbegin = i;
					blkexit = getBlockExit(mb,i);
				}
				OPTDEBUGstrengthReduction
					mnstr_printf(cntxt->fdout, "#check block %d-%d\n", blkbegin, blkexit);
			}
			within[ik++] = p;
			blk++;
			continue;
		}
		if (blockExit(p)) {
			blk--;
			if (blk == 0)
				blkexit= blkbegin = 0;
			/* move the saved instruction into place */
			OPTDEBUGstrengthReduction
				mnstr_printf(cntxt->fdout, "#combine both %d %d\n", bk, ik);
			for (k = 0; k < ik; k++)
				before[bk++] = within[k];
			ik = 0;
			before[bk++] = p;
			continue;
		}
		/*
		 * @-
		 * Strength reduction is only relevant inside a block;
		 */
		if( blkexit == 0) {
			within[ik++] = p;
			continue;
		}
		/*
		 * @-
		 * Flow control statements may not be moved around
		 */
		if ( p->barrier != 0){
			within[ik++] = p;
			continue;
		}
		/*
		 * @-
		 * Limit strength reduction to the type modules and the batcalc, batstr, batcolor
		 * and sql.bind.
		 */
		if(getModuleId(p) && !isNewSource(p) ) {
			within[ik++] = p;
			continue;
		}
		/*
		 * @-
		 * Search the prospective new block and make sure that
		 * none of the arguments is assigned a value.
		 */
		for (j = ik-1; j > 0; j--) {
			InstrPtr q = within[j];
			for (k = 0; k < q->retc; k++)
				if (SRoverwritten(p, getArg(q, k))) {
					se = TRUE;
					OPTDEBUGstrengthReduction
						mnstr_printf(cntxt->fdout, "variable is set in loop %d\n", getArg(p, k));
					goto noreduction;
				}
		}
		/*
		 * @-
		 * Make sure the variables are not declared before the loop and used
		 * after the loop, because then you may not simple move an expression.
		 */
		for (k = 0; k < p->retc; k++)
			if ( getBeginLifespan(span, getArg(p, k))<= blkbegin ||
				 getEndLifespan(span, getArg(p, k))> blkexit) {
				se = TRUE;
				OPTDEBUGstrengthReduction
					mnstr_printf(cntxt->fdout, "variable %d may not be moved %d-%d\n",
					getArg(p, k),getBeginLifespan(span, getArg(p, k)), getEndLifespan(span, getArg(p, k)));
				goto noreduction;
			}

  noreduction:
		OPTDEBUGstrengthReduction{
			mnstr_printf(cntxt->fdout,"move %d to stack %s\n", i, (se ?"within":"before"));
			printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL);
		}
		if (blkexit && se == FALSE && !hasSideEffects(p, TRUE) && !isUpdateInstruction(p) )
			before[bk++] = p;
		else
			within[ik++] = p;
	}
	actions += ik;
	for (k = 0; k < ik; k++)
		before[bk++] = within[k];
	before[bk++] = getInstrPtr(mb, i);
	GDKfree(mb->stmt);
	mb->stmt = (InstrPtr *) GDKzalloc((mb->ssize) * sizeof(InstrPtr));
	if ( mb->stmt == NULL){
		GDKfree(span);
		GDKfree(before);
		GDKfree(within);
		mb->stmt = old;
		return 0;
	}
	mb->stop = 0;

	OPTDEBUGstrengthReduction
		mnstr_printf(cntxt->fdout,"stop= %d bk=%d\n",mb->stop,bk);

	for (i = 0; i < bk; i++)
	if( before[i])
		pushInstruction(mb, before[i]);
	GDKfree(span);
	GDKfree(before);
	GDKfree(within);
	return actions;
}
Пример #29
0
static lng
SQLgetSpace(mvc *m, MalBlkPtr mb, int prepare)
{
	sql_trans *tr = m->session->tr;
	lng size,space = 0, i;
	str lasttable = 0;

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

		/* now deal with the update binds, it is only necessary to identify that there are updats
		 * The actual size is not that important */
		if (getModuleId(p) == sqlRef && getFunctionId(p) == bindRef  && p->retc <= 2){
			char *sname = getVarConstant(mb, getArg(p, 1 + p->retc)).val.sval;
			char *tname = getVarConstant(mb, getArg(p, 2 + p->retc)).val.sval;
			char *cname = getVarConstant(mb, getArg(p, 3 + p->retc)).val.sval;
			int access = getVarConstant(mb, getArg(p, 4 + p->retc)).val.ival;
			sql_schema *s = mvc_bind_schema(m, sname);
			sql_table *t = 0;
			sql_column *c = 0;

			if (!s || strcmp(s->base.name, dt_schema) == 0)
				continue;
			t = mvc_bind_table(m, s, tname);
			if (!t)
				continue;
			c = mvc_bind_column(m, t, cname);
			if (!s)
				continue;

			/* we have to sum the cost of all three components of a BAT */
			if (c && (!isRemote(c->t) && !isMergeTable(c->t)) && (lasttable == 0 || strcmp(lasttable,tname)==0)) {
				size = SQLgetColumnSize(tr, c, access);
				space += size;	// accumulate once per table
				//lasttable = tname;	 invalidate this attempt
				if( !prepare && size == 0  && ! t->system){
					//mnstr_printf(GDKout,"found empty column %s.%s.%s prepare %d size "LLFMT"\n",sname,tname,cname,prepare,size);
					setFunctionId(p, emptybindRef);
				}
			}
		}
		if (getModuleId(p) == sqlRef && (getFunctionId(p) == bindidxRef)) {
			char *sname = getVarConstant(mb, getArg(p, 1 + p->retc)).val.sval;
			//char *tname = getVarConstant(mb, getArg(p, 2 + p->retc)).val.sval;
			char *idxname = getVarConstant(mb, getArg(p, 3 + p->retc)).val.sval;
			int access = getVarConstant(mb, getArg(p, 4 + p->retc)).val.ival;
			sql_schema *s = mvc_bind_schema(m, sname);
			BAT *b;

			if (getFunctionId(p) == bindidxRef) {
				sql_idx *i = mvc_bind_idx(m, s, idxname);

				if (i && (!isRemote(i->t) && !isMergeTable(i->t))) {
					b = store_funcs.bind_idx(tr, i, RDONLY);
					if (b) {
						space += (size =getBatSpace(b));
						if (!size) {
							sql_column *c = i->t->columns.set->h->data;
							size = SQLgetColumnSize(tr, c, access);
						}

						if( !prepare && size == 0 && ! i->t->system){
							setFunctionId(p, emptybindidxRef);
							//mnstr_printf(GDKout,"found empty column %s.%s.%s prepare %d size "LLFMT"\n",sname,tname,idxname,prepare,size);
						}
						BBPunfix(b->batCacheid);
					}
				}
			}
		}
	}
	return space;
}
Пример #30
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;
}