int VALcmp(const ValRecord *p, const ValRecord *q) { int (*cmp)(const void *, const void *); int tpe; const void *nilptr, *pp, *pq; if (p == 0 || q == 0) return -1; if ((tpe = p->vtype) != q->vtype) return -1; if (tpe == TYPE_ptr) return 0; /* ignore comparing C pointers */ cmp = BATatoms[tpe].atomCmp; nilptr = ATOMnilptr(tpe); pp = VALptr(p); pq = VALptr(q); if ((*cmp)(pp, nilptr) == 0 && (*cmp)(pq, nilptr) == 0) return 0; /* eq nil val */ if ((*cmp)(pp, nilptr) == 0 || (*cmp)(pq, nilptr) == 0) return -1; return (*cmp)(pp, pq); }
/* Return TRUE if the value in V is NIL. */ int VALisnil(const ValRecord *v) { switch (v->vtype) { case TYPE_void: return 1; case TYPE_bte: return v->val.btval == bte_nil; case TYPE_sht: return v->val.shval == sht_nil; case TYPE_int: return v->val.ival == int_nil; case TYPE_wrd: return v->val.wval == wrd_nil; case TYPE_lng: return v->val.lval == lng_nil; #ifdef HAVE_HGE case TYPE_hge: return v->val.hval == hge_nil; #endif case TYPE_flt: return v->val.fval == flt_nil; case TYPE_dbl: return v->val.dval == dbl_nil; case TYPE_oid: return v->val.oval == oid_nil; case TYPE_bat: return v->val.bval == bat_nil || v->val.bval == 0; default: break; } return (*ATOMcompare(v->vtype))(VALptr(v), ATOMnilptr(v->vtype)) == 0; }
/* Return TRUE if the value in V is NIL. */ int VALisnil(const ValRecord *v) { switch (v->vtype) { case TYPE_void: return 1; case TYPE_bte: return is_bte_nil(v->val.btval); case TYPE_sht: return is_sht_nil(v->val.shval); case TYPE_int: return is_int_nil(v->val.ival); case TYPE_lng: return is_lng_nil(v->val.lval); #ifdef HAVE_HGE case TYPE_hge: return is_hge_nil(v->val.hval); #endif case TYPE_flt: return is_flt_nil(v->val.fval); case TYPE_dbl: return is_dbl_nil(v->val.dval); case TYPE_oid: return is_oid_nil(v->val.oval); case TYPE_bat: return is_bat_nil(v->val.bval); default: break; } return (*ATOMcompare(v->vtype))(VALptr(v), ATOMnilptr(v->vtype)) == 0; }
int VALisnil(const ValRecord *v) { switch (v->vtype) { case TYPE_void: return 1; case TYPE_bte: return v->val.btval == bte_nil; case TYPE_sht: return v->val.shval == sht_nil; case TYPE_int: case TYPE_bat: return v->val.ival == int_nil; case TYPE_lng: return v->val.lval == lng_nil; #ifdef HAVE_HGE case TYPE_hge: return v->val.hval == hge_nil; #endif case TYPE_flt: return v->val.fval == flt_nil; case TYPE_dbl: return v->val.dval == dbl_nil; default: break; } return (*BATatoms[v->vtype].atomCmp)(VALptr(v), ATOMnilptr(v->vtype)) == 0; }
int VALformat(char **buf, const ValRecord *res) { int t = res->vtype; *buf = 0; return ATOMformat(t, VALptr(res), buf); }
static str MDBgetFrame(BAT *b, BAT*bn, Client cntxt, MalBlkPtr mb, MalStkPtr s, int depth) { ValPtr v; int i; char *buf = 0; if (depth > 0) return MDBgetFrame(b,bn, cntxt, mb, s->up, depth - 1); if (s != 0) for (i = 0; i < s->stktop; i++, v++) { v = &s->stk[i]; ATOMformat(v->vtype, VALptr(v), &buf); BUNappend(b, getVarName(mb, i), FALSE); BUNappend(bn, buf, FALSE); GDKfree(buf); buf = NULL; } return MAL_SUCCEED; }
str CMDifthen(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { BAT *b = NULL, *b1 = NULL, *b2 = NULL, *bn; int tp0, tp1, tp2; bat *ret; BUN cnt = BUN_NONE; (void) cntxt; (void) mb; if (pci->argc != 4) throw(MAL, "batcalc.ifthen", "Operation not supported."); ret = getArgReference_bat(stk, pci, 0); tp0 = stk->stk[getArg(pci, 1)].vtype; tp1 = stk->stk[getArg(pci, 2)].vtype; tp2 = stk->stk[getArg(pci, 3)].vtype; if (tp0 == TYPE_bat || isaBatType(tp0)) { b = BATdescriptor(* getArgReference_bat(stk, pci, 1)); if (b == NULL) throw(MAL, "batcalc.ifthenelse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); cnt = BATcount(b); } if (tp1 == TYPE_bat || isaBatType(tp1)) { b1 = BATdescriptor(* getArgReference_bat(stk, pci, 2)); if (b1 == NULL) { if (b) BBPunfix(b->batCacheid); throw(MAL, "batcalc.ifthenelse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (cnt == BUN_NONE) cnt = BATcount(b1); else if (BATcount(b1) != cnt) { BBPunfix(b->batCacheid); throw(MAL, "batcalc.ifthenelse", ILLEGAL_ARGUMENT); } } if (tp2 == TYPE_bat || isaBatType(tp2)) { b2 = BATdescriptor(* getArgReference_bat(stk, pci, 3)); if (b2 == NULL) { if (b) BBPunfix(b->batCacheid); if (b1) BBPunfix(b1->batCacheid); throw(MAL, "batcalc.ifthenelse", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (cnt == BUN_NONE) cnt = BATcount(b2); else if (BATcount(b2) != cnt) { if (b) BBPunfix(b->batCacheid); if (b1) BBPunfix(b1->batCacheid); throw(MAL, "batcalc.ifthenelse", ILLEGAL_ARGUMENT); } } if (b == NULL && b1 == NULL && b2 == NULL) { /* at least one BAT required */ throw(MAL, "batcalc.ifthenelse", ILLEGAL_ARGUMENT); } if (b != NULL) { if (b1 != NULL) { if (b2 != NULL) { bn = BATcalcifthenelse(b, b1, b2); } else { bn = BATcalcifthenelsecst(b, b1, &stk->stk[getArg(pci, 3)]); } } else { if (b2 != NULL) { bn = BATcalcifthencstelse(b, &stk->stk[getArg(pci, 2)], b2); } else { bn = BATcalcifthencstelsecst(b, &stk->stk[getArg(pci, 2)], &stk->stk[getArg(pci, 3)]); } } } else { bit v = *getArgReference_bit(stk, pci, 1); if (is_bit_nil(v)) { if (b1 != NULL) bn = BATconstant(b1->hseqbase, b1->ttype, ATOMnilptr(b1->ttype), BATcount(b1), TRANSIENT); else bn = BATconstant(b2->hseqbase, b2->ttype, ATOMnilptr(b2->ttype), BATcount(b2), TRANSIENT); } else if (v) { if (b1 != NULL) bn = COLcopy(b1, b1->ttype, 0, TRANSIENT); else bn = BATconstant(b2->hseqbase, b2->ttype, VALptr(&stk->stk[getArg(pci, 2)]), BATcount(b2), TRANSIENT); } else { if (b2 != NULL) bn = COLcopy(b2, b2->ttype, 0, TRANSIENT); else bn = BATconstant(b1->hseqbase, b1->ttype, VALptr(&stk->stk[getArg(pci, 3)]), BATcount(b1), TRANSIENT); } } if (b) BBPunfix(b->batCacheid); if (b1) BBPunfix(b1->batCacheid); if (b2) BBPunfix(b2->batCacheid); if (bn == NULL) { return mythrow(MAL, "batcalc.ifthenelse", OPERATION_FAILED); } BBPkeepref(*ret = bn->batCacheid); return MAL_SUCCEED; }
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; }
/* Format the value in RES in the standard way for the type of RES * into a newly allocated buffer. Also see ATOMformat. */ char * VALformat(const ValRecord *res) { return ATOMformat(res->vtype, VALptr(res)); }