コード例 #1
0
ファイル: sql_atom.c プロジェクト: sekcheong/monetdb
atom *
atom_general(sql_allocator *sa, sql_subtype *tpe, char *val)
{
	atom *a;
	ptr p = NULL;

	if (atom_debug)
		fprintf(stderr, "atom_general(%s,%s)\n", tpe->type->sqlname, val);

	if (tpe->type->localtype == TYPE_str)
		return atom_string(sa, tpe, val);
	a = atom_create(sa);
	a->tpe = *tpe;
	a->data.val.pval = NULL;
	a->data.vtype = tpe->type->localtype;
	a->data.len = 0;

	assert(a->data.vtype >= 0);

	if (val) {
		int type = a->data.vtype;

		a->isnull = 0;
		if (ATOMstorage(type) == TYPE_str) {
			a->isnull = 0;
			a->data.val.sval = sql2str(sa_strdup(sa, val));
			a->data.len = (int)strlen(a->data.val.sval);
		} else { 
			int res = ATOMfromstr(type, &p, &a->data.len, val);

			/* no result or nil means error (SQL has NULL not nil) */
			if (res < 0 || !p || ATOMcmp(type, p, ATOMnilptr(type)) == 0) {
				/*_DELETE(val);*/
				if (p)
					GDKfree(p);
				return NULL;
			}
			VALset(&a->data, a->data.vtype, p);
			SA_VALcopy(sa, &a->data, &a->data);

			if (p && ATOMextern(a->data.vtype) == 0)
				GDKfree(p);
			/*_DELETE(val);*/
		}
	} else { 
		p = ATOMnilptr(a->data.vtype);
		VALset(&a->data, a->data.vtype, p);
		a->isnull = 1;
	}
	return a;
}
コード例 #2
0
ファイル: sql_atom.c プロジェクト: sekcheong/monetdb
atom *
atom_ptr( sql_allocator *sa, sql_subtype *tpe, void *v)
{
	atom *a = atom_create(sa);
	a->tpe = *tpe;
	a->isnull = 0;
	a->data.vtype = TYPE_ptr;
	VALset(&a->data, a->data.vtype, &v);
	a->data.len = 0;
	return a;
}
コード例 #3
0
ファイル: sql_optimizer.c プロジェクト: sekcheong/monetdb
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);
}
コード例 #4
0
ファイル: opt_pushranges.c プロジェクト: Clay-Birkett/monetdb
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;
}
コード例 #5
0
ファイル: opt_recycler.c プロジェクト: Clay-Birkett/monetdb
int
OPTrecyclerImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
{
	int i, j, cnt, tp, c, actions = 0, marks = 0, delta = 0;
	Lifespan span;
	InstrPtr *old, q;
	int limit, updstmt = 0;
	char *recycled;
	short app_sc = -1, in = 0;
	ValRecord cst;

	(void) cntxt;
	(void) stk;

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

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

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

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

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

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

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

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

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

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

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

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

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

		pushInstruction(mb, p);
	}