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 &&
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); }
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; }