str MDBgetStackFrameN(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p) { int n; bat *ret = getArgReference_bat(s, p, 0); bat *ret2 = getArgReference_bat(s, p, 1); BAT *b = BATnew(TYPE_void, TYPE_str, 256, TRANSIENT); BAT *bn = BATnew(TYPE_void, TYPE_str, 256, TRANSIENT); if (b == 0 || bn == 0) { BBPreclaim(b); BBPreclaim(bn); throw(MAL, "mdb.getStackFrame", MAL_MALLOC_FAIL); } BATseqbase(b,0); BATseqbase(bn,0); n = *getArgReference_int(s, p, 2); if (n < 0 || n >= getStkDepth(s)){ BBPunfix(b->batCacheid); throw(MAL, "mdb.getStackFrame", ILLEGAL_ARGUMENT " Illegal depth."); } pseudo(ret,b,"view","stk","frame"); pseudo(ret2,bn,"view","stk","frameB"); return MDBgetFrame(b, bn, cntxt, m, s, n); }
str CMDcalcavg(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { dbl avg; BUN vals; bat *bid; BAT *b, *s = NULL; gdk_return ret; (void) cntxt; (void) mb; bid = getArgReference_bat(stk, pci, pci->retc + 0); if ((b = BATdescriptor(*bid)) == NULL) throw(MAL, "aggr.avg", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); if (pci->retc == pci->retc + 2) { bat *sid = getArgReference_bat(stk, pci, pci->retc + 1); if (*sid && (s = BATdescriptor(*sid)) == NULL) { BBPunfix(b->batCacheid); throw(MAL, "aggr.avg", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } ret = BATcalcavg(b, s, &avg, &vals); BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); if (ret != GDK_SUCCEED) return mythrow(MAL, "aggr.avg", OPERATION_FAILED); * getArgReference_dbl(stk, pci, 0) = avg; if (pci->retc == 2) * getArgReference_lng(stk, pci, 1) = vals; return MAL_SUCCEED; }
static str CMDconvertbat(MalStkPtr stk, InstrPtr pci, int tp, int abort_on_error) { bat *bid; BAT *b, *bn, *s = NULL; bid = getArgReference_bat(stk, pci, 1); if ((b = BATdescriptor(*bid)) == NULL) throw(MAL, "batcalc.convert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); if (pci->argc == 3) { bat *sid = getArgReference_bat(stk, pci, 2); if (*sid && (s = BATdescriptor(*sid)) == NULL) { BBPunfix(b->batCacheid); throw(MAL, "batcalc.convert", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } bn = BATconvert(b, s, tp, abort_on_error); BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); if (bn == NULL) { char buf[20]; snprintf(buf, sizeof(buf), "batcalc.%s", ATOMname(tp)); return mythrow(MAL, buf, OPERATION_FAILED); } bid = getArgReference_bat(stk, pci, 0); BBPkeepref(*bid = bn->batCacheid); return MAL_SUCCEED; }
static str CMDbatUNARY1(MalStkPtr stk, InstrPtr pci, int abort_on_error, BAT *(*batfunc)(BAT *, BAT *, int), const char *malfunc) { bat *bid; BAT *bn, *b, *s = NULL; bid = getArgReference_bat(stk, pci, 1); if ((b = BATdescriptor(*bid)) == NULL) throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); if (pci->argc == 3) { bat *sid = getArgReference_bat(stk, pci, 2); if (*sid && (s = BATdescriptor(*sid)) == NULL) { BBPunfix(b->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } bn = (*batfunc)(b, s, abort_on_error); BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); if (bn == NULL) { return mythrow(MAL, malfunc, OPERATION_FAILED); } bid = getArgReference_bat(stk, pci, 0); BBPkeepref(*bid = bn->batCacheid); return MAL_SUCCEED; }
str GROUPmulticolumngroup(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { bat *grp = getArgReference_bat(stk, pci, 0); bat *ext = getArgReference_bat(stk, pci, 1); bat *hist = getArgReference_bat(stk, pci, 2); int i, j; bat oldgrp, oldext, oldhist; str msg = MAL_SUCCEED; BAT *b; BUN count = 0; AGGRtask *aggr; aggr = GROUPcollect(cntxt, mb, stk, pci); if( aggr == NULL) throw(MAL,"group.multicolumn", SQLSTATE(HY001) MAL_MALLOC_FAIL); GROUPcollectSort(aggr, 0, aggr->last); /* (grp,ext,hist) := group.group(..) */ /* use the old pattern to perform the incremental grouping */ *grp = 0; *ext = 0; *hist = 0; msg = GRPgroup1(grp, ext, hist, &aggr->bid[0]); i = 1; if (msg == MAL_SUCCEED && aggr->last > 1) do { /* early break when there are as many groups as entries */ b = BATdescriptor(*hist); if (b) { j = BATcount(b) == count; BBPunfix(*hist); if (j) break; } /* (grp,ext,hist) := group.subgroup(arg,grp,ext,hist) */ oldgrp = *grp; oldext = *ext; oldhist = *hist; *grp = 0; *ext = 0; *hist = 0; msg = GRPsubgroup5(grp, ext, hist, &aggr->bid[i], NULL, &oldgrp, &oldext, &oldhist); BBPrelease(oldgrp); BBPrelease(oldext); BBPrelease(oldhist); } while (msg == MAL_SUCCEED && ++i < aggr->last); GROUPdelete(aggr); return msg; }
str ITRbunNext(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { BATiter bi; BAT *b; oid *head; bat *bid; ValPtr tail; (void) cntxt; (void) mb; head = getArgReference_oid(stk, pci, 0); tail = &stk->stk[pci->argv[1]]; bid = getArgReference_bat(stk, pci, 2); if ((b = BATdescriptor(*bid)) == NULL) { throw(MAL, "iterator.nextChunk", INTERNAL_BAT_ACCESS); } *head = (BUN)*head + 1; if (*head >= BUNlast(b)) { *head = oid_nil; BBPunfix(b->batCacheid); return MAL_SUCCEED; } bi = bat_iterator(b); VALinit(tail, b->ttype, BUNtail(bi, *(BUN*) head)); BBPunfix(b->batCacheid); return MAL_SUCCEED; }
str db_password_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { (void) mb; if (stk->stk[pci->argv[0]].vtype == TYPE_bat) { BAT *b = BATdescriptor(*getArgReference_bat(stk, pci, 1)); if (b == NULL) throw(SQL, "sql.password", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); BAT *bn = COLnew(b->hseqbase, TYPE_str, BATcount(b), TRANSIENT); if (bn == NULL) { BBPunfix(b->batCacheid); throw(SQL, "sql.password", SQLSTATE(HY001) MAL_MALLOC_FAIL); } BATiter bi = bat_iterator(b); BUN p, q; BATloop(b, p, q) { char *hash, *msg; msg = AUTHgetPasswordHash(&hash, cntxt, BUNtvar(bi, p)); if (msg != MAL_SUCCEED) { BBPunfix(b->batCacheid); BBPreclaim(bn); return msg; } if (BUNappend(bn, hash, false) != GDK_SUCCEED) { BBPunfix(b->batCacheid); BBPreclaim(bn); throw(SQL, "sql.password", SQLSTATE(HY001) MAL_MALLOC_FAIL); } GDKfree(hash); }
str MATpackValues(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { int i, type, first = 1; bat *ret; BAT *bn; (void) cntxt; type = getArgType(mb,p,first); bn = BATnew(TYPE_void, type, p->argc, TRANSIENT); if( bn == NULL) throw(MAL, "mat.pack", MAL_MALLOC_FAIL); if (ATOMextern(type)) { for(i = first; i < p->argc; i++) BUNappend(bn, stk->stk[getArg(p,i)].val.pval, TRUE); } else { for(i = first; i < p->argc; i++) BUNappend(bn, getArgReference(stk, p, i), TRUE); } BATseqbase(bn, 0); ret= getArgReference_bat(stk,p,0); BBPkeepref(*ret = bn->batCacheid); return MAL_SUCCEED; }
str MDBgetStackFrame(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p) { bat *ret = getArgReference_bat(s, p, 0); bat *ret2 = getArgReference_bat(s, p, 1); BAT *b = BATnew(TYPE_void, TYPE_str, 256, TRANSIENT); BAT *bn = BATnew(TYPE_void, TYPE_str, 256, TRANSIENT); if (b == 0 || bn == 0) { BBPreclaim(b); BBPreclaim(bn); throw(MAL, "mdb.getStackFrame", MAL_MALLOC_FAIL); } BATseqbase(b,0); BATseqbase(bn,0); pseudo(ret,b,"view","stk","frame"); pseudo(ret2,bn,"view","stk","frame"); return MDBgetFrame(b,bn, cntxt, m, s, 0); }
/* * Enable incremental packing. The SQL front-end requires * fixed oid sequences. */ str MATpackIncrement(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { bat *ret = getArgReference_bat(stk,p,0); int pieces; BAT *b, *bb, *bn; size_t newsize; (void) cntxt; b = BATdescriptor( stk->stk[getArg(p,1)].val.ival); if ( b == NULL) throw(MAL, "mat.pack", RUNTIME_OBJECT_MISSING); if ( getArgType(mb,p,2) == TYPE_int){ /* first step, estimate with some slack */ pieces = stk->stk[getArg(p,2)].val.ival; bn = BATnew(TYPE_void, b->ttype?b->ttype:TYPE_oid, (BUN)(1.2 * BATcount(b) * pieces), TRANSIENT); if (bn == NULL) throw(MAL, "mat.pack", MAL_MALLOC_FAIL); /* allocate enough space for the vheap, but not for strings, * since BATappend does clever things for strings */ if ( b->T->vheap && bn->T->vheap && ATOMstorage(b->ttype) != TYPE_str){ newsize = b->T->vheap->size * pieces; if (HEAPextend(bn->T->vheap, newsize, TRUE) != GDK_SUCCEED) throw(MAL, "mat.pack", MAL_MALLOC_FAIL); } BATseqbase(bn, b->H->seq); BATseqbase(BATmirror(bn), b->T->seq); BATappend(bn,b,FALSE); assert(!bn->H->nil || !bn->H->nonil); assert(!bn->T->nil || !bn->T->nonil); bn->H->align = (pieces-1); BBPkeepref(*ret = bn->batCacheid); BBPunfix(b->batCacheid); } else { /* remaining steps */ bb = BATdescriptor(stk->stk[getArg(p,2)].val.ival); if ( bb ){ if (BATcount(b) == 0) BATseqbase(b, bb->H->seq); if (BATcount(b) == 0) BATseqbase(BATmirror(b), bb->T->seq); BATappend(b,bb,FALSE); } b->H->align--; if(b->H->align == 0) BATsetaccess(b, BAT_READ); assert(!b->H->nil || !b->H->nonil); assert(!b->T->nil || !b->T->nonil); BBPkeepref(*ret = b->batCacheid); if( bb) BBPunfix(bb->batCacheid); } return MAL_SUCCEED; }
static AGGRtask* GROUPcollect( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ AGGRtask *a; int i; BAT *b, *bs, *bh = NULL; BUN sample; (void) mb; (void) cntxt; a= (AGGRtask *) GDKzalloc(sizeof(*a)); if ( a == NULL) return NULL; a->bid = (bat*) GDKzalloc(pci->argc * sizeof(bat)); a->cols = (BAT**) GDKzalloc(pci->argc * sizeof(BAT*)); a->unique = (BUN *) GDKzalloc(pci->argc * sizeof(BUN)); if ( a->cols == NULL || a->bid == NULL || a->unique == NULL){ if(a->cols) GDKfree(a->cols); if(a->bid) GDKfree(a->bid); if(a->unique) GDKfree(a->unique); GDKfree(a); return NULL; } for ( i= pci->retc; i< pci->argc; i++, a->last++) { a->bid[a->last] = *getArgReference_bat(stk,pci,i); b = a->cols[a->last]= BATdescriptor(a->bid[a->last]); if ( a->cols[a->last] == NULL){ for(a->last--; a->last>=0; a->last--) BBPunfix(a->cols[a->last]->batCacheid); GDKfree(a->cols); GDKfree(a->bid); GDKfree(a->unique); GDKfree(a); return NULL; } sample = BATcount(b) < 1000 ? BATcount(b): 1000; bs = BATsample( b, sample); if (bs) { bh = BATunique(b, bs); if (bh) { a->unique[a->last] = BATcount(bh); BBPunfix(bh->batCacheid); } BBPunfix(bs->batCacheid); } if ( b->tsorted) a->unique[a->last] = 1000; /* sorting helps grouping */ a->size = BATcount(b); } #ifdef _DEBUG_GROUPBY_ for(i=0; i<a->last; i++) fprintf(stderr,"#group %d unique "BUNFMT "\n", i, a->unique[i]); #endif return a; }
str JSONfold(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { bat *id = 0, *key = 0, *val = 0; str *ret; (void) cntxt; (void) mb; assert(pci->retc == 1); if (pci->argc - pci->retc == 1) { val = getArgReference_bat(stk, pci, 1); } else if (pci->argc - pci->retc == 2) { id = 0; key = getArgReference_bat(stk, pci, 1); val = getArgReference_bat(stk, pci, 2); } else { assert(pci->argc - pci->retc == 3); id = getArgReference_bat(stk, pci, 1); key = getArgReference_bat(stk, pci, 2); val = getArgReference_bat(stk, pci, 3); } ret = getArgReference_TYPE(stk, pci, 0, json); return JSONfoldKeyValue(ret, id, key, val); }
str SQLdiff(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { (void)cntxt; if (isaBatType(getArgType(mb, pci, 1))) { bat *res = getArgReference_bat(stk, pci, 0); bat *bid = getArgReference_bat(stk, pci, 1); BAT *b = BATdescriptor(*bid), *c, *r; gdk_return gdk_code; if (!b) throw(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor"); voidresultBAT(r, TYPE_bit, BATcount(b), b, "sql.diff"); if (pci->argc > 2) { c = b; bid = getArgReference_bat(stk, pci, 2); b = BATdescriptor(*bid); if (!b) { BBPunfix(c->batCacheid); throw(SQL, "sql.diff", SQLSTATE(HY005) "Cannot access column descriptor"); } gdk_code = GDKanalyticaldiff(r, b, c, b->ttype); BBPunfix(c->batCacheid); } else { gdk_code = GDKanalyticaldiff(r, b, NULL, b->ttype); } BBPunfix(b->batCacheid); if(gdk_code == GDK_SUCCEED) BBPkeepref(*res = r->batCacheid); else throw(SQL, "sql.diff", GDK_EXCEPTION); } else { bit *res = getArgReference_bit(stk, pci, 0); *res = FALSE; } return MAL_SUCCEED; }
str db_users_wrap(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { bat *r = getArgReference_bat(stk, pci, 0); BAT *uid, *nme; str err; (void) mb; if ((err = AUTHgetUsers(&uid, &nme, cntxt)) != MAL_SUCCEED) return err; BBPunfix(uid->batCacheid); *r = nme->batCacheid; BBPkeepref(*r); return MAL_SUCCEED; }
/* * The pack is an ordinary multi BAT insert. Oid synchronistion * between pieces should be ensured by the code generators. * The pack operation could be quite expensive, because it * may create a really large BAT. * The slice over a mat helps to avoid constructing intermediates * that are subsequently reduced. * Contrary to most operations, NIL arguments are skipped and * do not produce RUNTIME_OBJECT_MISSING. */ static str MATpackInternal(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { int i; bat *ret = getArgReference_bat(stk,p,0); BAT *b, *bn; BUN cap = 0; int tt = TYPE_any; (void) cntxt; (void) mb; for (i = 1; i < p->argc; i++) { bat bid = stk->stk[getArg(p,i)].val.bval; b = BBPquickdesc(abs(bid),FALSE); if( b ){ if (tt == TYPE_any) tt = b->ttype; if (tt != b->ttype) throw(MAL, "mat.pack", "incompatible arguments"); cap += BATcount(b); } } if (tt == TYPE_any){ *ret = bat_nil; return MAL_SUCCEED; } bn = BATnew(TYPE_void, tt, cap, TRANSIENT); if (bn == NULL) throw(MAL, "mat.pack", MAL_MALLOC_FAIL); for (i = 1; i < p->argc; i++) { b = BATdescriptor(stk->stk[getArg(p,i)].val.ival); if( b ){ if (BATcount(bn) == 0) BATseqbase(bn, b->H->seq); if (BATcount(bn) == 0) BATseqbase(BATmirror(bn), b->T->seq); BATappend(bn,b,FALSE); BBPunfix(b->batCacheid); } } assert(!bn->T->nil || !bn->T->nonil); BATsettrivprop(bn); BATderiveProps(bn,FALSE); BBPkeepref(*ret = bn->batCacheid); return MAL_SUCCEED; }
str TRNtrans_abort(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) { int i; bat *bid; BAT *b; (void) cntxt; (void) mb; for (i = p->retc; i < p->argc; i++) { bid = getArgReference_bat(stk, p, i); if ((b = BATdescriptor(*bid)) == NULL) { throw(MAL, "transaction.abort", RUNTIME_OBJECT_MISSING); } BATundo(b); BBPunfix(b->batCacheid); } return MAL_SUCCEED; }
/* * It is illustrative to dump the code when you * have encountered an error. */ str MDBgetDefinition(Client cntxt, MalBlkPtr m, MalStkPtr stk, InstrPtr p) { int i; bat *ret = getArgReference_bat(stk, p, 0); str ps; BAT *b = BATnew(TYPE_void, TYPE_str, 256, TRANSIENT); (void) cntxt; if (b == 0) throw(MAL, "mdb.getDefinition", MAL_MALLOC_FAIL); BATseqbase(b,0); for (i = 0; i < m->stop; i++) { ps = instruction2str(m,0, getInstrPtr(m, i), 1); BUNappend(b, ps, FALSE); GDKfree(ps); } if (!(b->batDirty&2)) BATsetaccess(b, BAT_READ); pseudo(ret,b,"view","fcn","stmt"); return MAL_SUCCEED; }
str JSONunfold(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { bat *id = 0, *key = 0, *val = 0; json *js; (void) cntxt; (void) mb; if (pci->retc == 1) { val = getArgReference_bat(stk, pci, 0); } else if (pci->retc == 2) { id = 0; key = getArgReference_bat(stk, pci, 0); val = getArgReference_bat(stk, pci, 1); } else if (pci->retc == 3) { id = getArgReference_bat(stk, pci, 0); key = getArgReference_bat(stk, pci, 1); val = getArgReference_bat(stk, pci, 2); } js = getArgReference_TYPE(stk, pci, pci->retc, json); return JSONunfoldInternal(id, key, val, js); }
static str CMDbatBINARY2(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, BAT *(*batfunc)(BAT *, BAT *, BAT *, int, int), BAT *(batfunc1)(BAT *, const ValRecord *, BAT *, int, int), BAT *(batfunc2)(const ValRecord *, BAT *, BAT *, int, int), int (*typefunc)(int, int), int abort_on_error, const char *malfunc) { bat *bid; BAT *bn, *b, *s = NULL; int tp1, tp2, tp3; tp1 = stk->stk[getArg(pci, 1)].vtype; tp2 = stk->stk[getArg(pci, 2)].vtype; tp3 = getArgType(mb, pci, 0); assert(isaBatType(tp3)); tp3 = getBatType(tp3); if (pci->argc == 4) { bat *sid = getArgReference_bat(stk, pci, 3); if (*sid && (s = BATdescriptor(*sid)) == NULL) throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp1 == TYPE_bat || isaBatType(tp1)) { BAT *b2 = NULL; bid = getArgReference_bat(stk, pci, 1); b = BATdescriptor(*bid); if (b == NULL) { if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp2 == TYPE_bat || isaBatType(tp2)) { bid = getArgReference_bat(stk, pci, 2); b2 = BATdescriptor(*bid); if (b2 == NULL) { BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } if (b2) { if (tp3 == TYPE_any) tp3 = (*typefunc)(b->ttype, b2->ttype); bn = (*batfunc)(b, b2, s, tp3, abort_on_error); BBPunfix(b2->batCacheid); } else { if (tp3 == TYPE_any) tp3 = (*typefunc)(b->ttype, tp2); bn = (*batfunc1)(b, &stk->stk[getArg(pci, 2)], s, tp3, abort_on_error); } } else { assert(tp1 != TYPE_bat && !isaBatType(tp1)); assert(tp2 == TYPE_bat || isaBatType(tp2)); bid = getArgReference_bat(stk, pci, 2); b = BATdescriptor(*bid); if (b == NULL) { if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp3 == TYPE_any) tp3 = (*typefunc)(tp1, b->ttype); bn = (*batfunc2)(&stk->stk[getArg(pci, 1)], b, s, tp3, abort_on_error); } BBPunfix(b->batCacheid); if (bn == NULL) { return mythrow(MAL, malfunc, OPERATION_FAILED); } bid = getArgReference_bat(stk, pci, 0); BBPkeepref(*bid = bn->batCacheid); return MAL_SUCCEED; }
str MDBStkTrace(Client cntxt, MalBlkPtr m, MalStkPtr s, InstrPtr p) { BAT *b, *bn; str msg; char *buf; bat *ret = getArgReference_bat(s, p, 0); bat *ret2 = getArgReference_bat(s, p, 1); int k = 0; size_t len,l; b = BATnew(TYPE_void, TYPE_int, 256, TRANSIENT); if ( b== NULL) throw(MAL, "mdb.getStackTrace", MAL_MALLOC_FAIL); bn = BATnew(TYPE_void, TYPE_str, 256, TRANSIENT); if ( bn== NULL) { BBPreclaim(b); throw(MAL, "mdb.getStackTrace", MAL_MALLOC_FAIL); } BATseqbase(b,0); BATseqbase(bn,0); (void) cntxt; msg = instruction2str(s->blk, s, p, LIST_MAL_DEBUG); len = strlen(msg); buf = (char*) GDKmalloc(len +1024); if ( buf == NULL){ GDKfree(msg); throw(MAL,"mdb.setTrace",MAL_MALLOC_FAIL); } snprintf(buf,len+1024,"%s at %s.%s[%d]", msg, getModuleId(getInstrPtr(m,0)), getFunctionId(getInstrPtr(m,0)), getPC(m, p)); BUNappend(b, &k, FALSE); BUNappend(bn, buf, FALSE); GDKfree(msg); for (s = s->up, k++; s != NULL; s = s->up, k++) { msg = instruction2str(s->blk, s, getInstrPtr(s->blk,s->pcup),LIST_MAL_DEBUG); l = strlen(msg); if (l>len){ GDKfree(buf); len=l; buf = (char*) GDKmalloc(len +1024); if ( buf == NULL){ GDKfree(msg); BBPunfix(b->batCacheid); BBPunfix(bn->batCacheid); throw(MAL,"mdb.setTrace",MAL_MALLOC_FAIL); } } snprintf(buf,len+1024,"%s at %s.%s[%d]", msg, getModuleId(getInstrPtr(s->blk,0)), getFunctionId(getInstrPtr(s->blk,0)), s->pcup); BUNappend(b, &k, FALSE); BUNappend(bn, buf, FALSE); GDKfree(msg); } GDKfree(buf); if (!(b->batDirty&2)) BATsetaccess(b, BAT_READ); if (!(bn->batDirty&2)) BATsetaccess(bn, BAT_READ); pseudo(ret,b,"view","stk","trace"); pseudo(ret2,bn,"view","stk","traceB"); return MAL_SUCCEED; }
str SQLwindow_bound(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { str msg = MAL_SUCCEED; bool preceding; lng first_half; int unit, bound, excl, part_offset = (pci->argc > 6); if ((pci->argc != 6 && pci->argc != 7) || getArgType(mb, pci, part_offset + 2) != TYPE_int || getArgType(mb, pci, part_offset + 3) != TYPE_int || getArgType(mb, pci, part_offset + 4) != TYPE_int) { throw(SQL, "sql.window_bound", SQLSTATE(42000) "Invalid arguments"); } unit = *getArgReference_int(stk, pci, part_offset + 2); bound = *getArgReference_int(stk, pci, part_offset + 3); excl = *getArgReference_int(stk, pci, part_offset + 4); assert(unit >= 0 && unit <= 3); assert(bound >= 0 && bound <= 5); assert(excl >= 0 && excl <= 2); preceding = (bound % 2 == 0); first_half = (bound < 2 || bound == 4); (void)cntxt; if (isaBatType(getArgType(mb, pci, 1))) { bat *res = getArgReference_bat(stk, pci, 0); BAT *b = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 1)), *p = NULL, *r, *l = NULL; int tp1 = getBatType(getArgType(mb, pci, part_offset + 1)), tp2 = getArgType(mb, pci, part_offset + 5); void* limit = NULL; bool is_negative = false, is_null = false, is_a_bat; gdk_return gdk_code; if (!b) throw(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor"); if (excl != 0) { BBPunfix(b->batCacheid); throw(SQL, "sql.window_bound", SQLSTATE(42000) "Only EXCLUDE NO OTHERS exclusion is currently implemented"); } is_a_bat = isaBatType(tp2); if(is_a_bat) tp2 = getBatType(tp2); voidresultBAT(r, TYPE_lng, BATcount(b), b, "sql.window_bound"); if(is_a_bat) { //SQL_CURRENT_ROW shall never fall in limit validation l = BATdescriptor(*getArgReference_bat(stk, pci, part_offset + 5)); if (!l) { BBPunfix(b->batCacheid); throw(SQL, "sql.window_bound", SQLSTATE(HY005) "Cannot access column descriptor"); } switch (tp2) { case TYPE_bte: CHECK_NULLS_AND_NEGATIVES_COLUMN(bte) break; case TYPE_sht: CHECK_NULLS_AND_NEGATIVES_COLUMN(sht) break; case TYPE_int: CHECK_NULLS_AND_NEGATIVES_COLUMN(int) break; case TYPE_lng: CHECK_NULLS_AND_NEGATIVES_COLUMN(lng) break; case TYPE_flt: CHECK_NULLS_AND_NEGATIVES_COLUMN(flt) break; case TYPE_dbl: CHECK_NULLS_AND_NEGATIVES_COLUMN(dbl) break; #ifdef HAVE_HGE case TYPE_hge: CHECK_NULLS_AND_NEGATIVES_COLUMN(hge) break; #endif default: { BBPunfix(b->batCacheid); BBPunfix(l->batCacheid); throw(SQL, "sql.window_bound", SQLSTATE(42000) "%s limit not available for %s", "sql.window_bound", ATOMname(tp2)); } } if(is_null || is_negative) { BBPunfix(b->batCacheid); BBPunfix(l->batCacheid); if(is_null) throw(SQL, "sql.window_bound", SQLSTATE(HY005) "All values on %s boundary must be non-null", preceding ? "PRECEDING" : "FOLLOWING"); throw(SQL, "sql.window_bound", SQLSTATE(HY005) "All values on %s boundary must be non-negative", preceding ? "PRECEDING" : "FOLLOWING"); } } else {
str BATXMLforest(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) { bat *ret = getArgReference_bat(stk, pci, 0); BAT *bn; BATiter *bi; BUN *p, *q; str buf; int i; size_t offset, len, size = BUFSIZ; const char *err = OPERATION_FAILED; (void) mb; (void) cntxt; buf = GDKmalloc(size); bi = GDKmalloc(sizeof(BATiter) * pci->argc); p = GDKmalloc(sizeof(BUN) * pci->argc); q = GDKmalloc(sizeof(BUN) * pci->argc); if (buf == NULL || bi == NULL || p == NULL || q == NULL) { if (buf) GDKfree(buf); if (bi) GDKfree(bi); if (p) GDKfree(p); if (q) GDKfree(q); throw(MAL, "xml.forest", MAL_MALLOC_FAIL); } /* collect the admin for the xml elements */ for (i = pci->retc; i < pci->argc; i++) { if ((bi[i].b = BATdescriptor(*getArgReference_bat(stk, pci, i))) == NULL) break; p[i] = BUNfirst(bi[i].b); q[i] = BUNlast(bi[i].b); } /* check for errors */ if (i != pci->argc) { for (i--; i >= pci->retc; i--) if (bi[i].b) BBPunfix(bi[i].b->batCacheid); GDKfree(bi); GDKfree(p); GDKfree(q); GDKfree(buf); throw(MAL, "xml.forest", INTERNAL_BAT_ACCESS); } prepareResult(bn, bi[pci->retc].b, TYPE_xml, "forest", for (i = pci->retc; i < pci->argc; i++) BBPunfix(bi[i].b->batCacheid); GDKfree(bi); GDKfree(p); GDKfree(q); GDKfree(buf)); while (p[pci->retc] < q[pci->retc]) { const char *t; /* fetch the elements */ offset = 0; strcpy(buf, str_nil); for (i = pci->retc; i < pci->argc; i++) { int n; t = (const char *) BUNtail(bi[i], p[i]); if (strNil(t)) continue; if ((len = strlen(t)) >= size - offset) { size += len + 128; buf = GDKrealloc(buf, size); if (buf == NULL) { err = MAL_MALLOC_FAIL; goto bunins_failed; } } if (offset == 0) n = snprintf(buf, size, "%s", t); else if (buf[0] != *t) { err = "incompatible values in forest"; goto bunins_failed; } else if (buf[0] == 'A') n = snprintf(buf + offset, size - offset, " %s", t + 1); else if (buf[0] == 'C') n = snprintf(buf + offset, size - offset, "%s", t + 1); else { err = "can only combine attributes and element content"; goto bunins_failed; } offset += n; } bunfastapp(bn, buf); if (offset == 0) bn->T->nonil = 0; for (i = pci->retc; i < pci->argc; i++) if (bi[i].b) p[i]++; } GDKfree(buf); finalizeResult(ret, bn, bi[pci->retc].b); GDKfree(bi); GDKfree(p); GDKfree(q); return MAL_SUCCEED; bunins_failed: for (i = pci->retc; i < pci->argc; i++) if (bi[i].b) BBPunfix(bi[i].b->batCacheid); BBPunfix(bn->batCacheid); if (buf != NULL) GDKfree(buf); GDKfree(bi); GDKfree(p); GDKfree(q); throw(MAL, "xml.forest", "%s", err); }
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; }
static str callbatBETWEEN(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int sym) { bat *bid; BAT *bn, *b, *lo = NULL, *hi = NULL, *s = NULL; int tp1, tp2, tp3; (void) cntxt; (void) mb; tp1 = stk->stk[getArg(pci, 1)].vtype; tp2 = stk->stk[getArg(pci, 2)].vtype; tp3 = stk->stk[getArg(pci, 3)].vtype; if (pci->argc == 5) { bat *sid = getArgReference_bat(stk, pci, 4); if (*sid && (s = BATdescriptor(*sid)) == NULL) throw(MAL, "batcalc.between", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp1 != TYPE_bat && !isaBatType(tp1)) { if (s) BBPunfix(s->batCacheid); throw(MAL, "batcalc.between", ILLEGAL_ARGUMENT); } bid = getArgReference_bat(stk, pci, 1); b = BATdescriptor(*bid); if (b == NULL) { if (s) BBPunfix(s->batCacheid); throw(MAL, "batcalc.between", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp2 == TYPE_bat || isaBatType(tp2)) { bid = getArgReference_bat(stk, pci, 2); lo = BATdescriptor(*bid); if (lo == NULL) { BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); throw(MAL, "batcalc.between", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } if (tp3 == TYPE_bat || isaBatType(tp3)) { bid = getArgReference_bat(stk, pci, 3); hi = BATdescriptor(*bid); if (hi == NULL) { BBPunfix(b->batCacheid); if (lo) BBPunfix(lo->batCacheid); if (s) BBPunfix(s->batCacheid); throw(MAL, "batcalc.between", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } if (lo == NULL) { if (hi == NULL) { bn = BATcalcbetweencstcst(b, &stk->stk[getArg(pci, 2)], &stk->stk[getArg(pci, 3)], s, sym); } else { bn = BATcalcbetweencstbat(b, &stk->stk[getArg(pci, 2)], hi, s, sym); } } else { if (hi == NULL) { bn = BATcalcbetweenbatcst(b, lo, &stk->stk[getArg(pci, 3)], s, sym); } else { bn = BATcalcbetween(b, lo, hi, s, sym); } } BBPunfix(b->batCacheid); if (lo) BBPunfix(lo->batCacheid); if (hi) BBPunfix(hi->batCacheid); if (s) BBPunfix(s->batCacheid); if (bn == NULL) { return mythrow(MAL, "batcalc.between", OPERATION_FAILED); } bid = getArgReference_bat(stk, pci, 0); BBPkeepref(*bid = bn->batCacheid); return MAL_SUCCEED; }
str RAPIeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, bit grouped) { sql_func * sqlfun = NULL; str exprStr = *getArgReference_str(stk, pci, pci->retc + 1); SEXP x, env, retval; SEXP varname = R_NilValue; SEXP varvalue = R_NilValue; ParseStatus status; int i = 0; char argbuf[64]; char *argnames = NULL; size_t argnameslen; size_t pos; char* rcall = NULL; size_t rcalllen; int ret_cols = 0; /* int because pci->retc is int, too*/ str *args; int evalErr; char *msg = MAL_SUCCEED; BAT *b; node * argnode; int seengrp = FALSE; rapiClient = cntxt; if (!RAPIEnabled()) { throw(MAL, "rapi.eval", "Embedded R has not been enabled. Start server with --set %s=true", rapi_enableflag); } if (!rapiInitialized) { throw(MAL, "rapi.eval", "Embedded R initialization has failed"); } if (!grouped) { sql_subfunc *sqlmorefun = (*(sql_subfunc**) getArgReference(stk, pci, pci->retc)); if (sqlmorefun) sqlfun = (*(sql_subfunc**) getArgReference(stk, pci, pci->retc))->func; } else { sqlfun = *(sql_func**) getArgReference(stk, pci, pci->retc); } args = (str*) GDKzalloc(sizeof(str) * pci->argc); if (args == NULL) { throw(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); } // get the lock even before initialization of the R interpreter, as this can take a second and must be done only once. MT_lock_set(&rapiLock); env = PROTECT(eval(lang1(install("new.env")), R_GlobalEnv)); assert(env != NULL); // first argument after the return contains the pointer to the sql_func structure // NEW macro temporarily renamed to MNEW to allow including sql_catalog.h if (sqlfun != NULL && sqlfun->ops->cnt > 0) { int carg = pci->retc + 2; argnode = sqlfun->ops->h; while (argnode) { char* argname = ((sql_arg*) argnode->data)->name; args[carg] = GDKstrdup(argname); carg++; argnode = argnode->next; } } // the first unknown argument is the group, we don't really care for the rest. argnameslen = 2; for (i = pci->retc + 2; i < pci->argc; i++) { if (args[i] == NULL) { if (!seengrp && grouped) { args[i] = GDKstrdup("aggr_group"); seengrp = TRUE; } else { snprintf(argbuf, sizeof(argbuf), "arg%i", i - pci->retc - 1); args[i] = GDKstrdup(argbuf); } } argnameslen += strlen(args[i]) + 2; /* extra for ", " */ } // install the MAL variables into the R environment // we can basically map values to int ("INTEGER") or double ("REAL") for (i = pci->retc + 2; i < pci->argc; i++) { int bat_type = getBatType(getArgType(mb,pci,i)); // check for BAT or scalar first, keep code left if (!isaBatType(getArgType(mb,pci,i))) { b = COLnew(0, getArgType(mb, pci, i), 0, TRANSIENT); if (b == NULL) { msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } if ( getArgType(mb,pci,i) == TYPE_str) { if (BUNappend(b, *getArgReference_str(stk, pci, i), false) != GDK_SUCCEED) { BBPreclaim(b); b = NULL; msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } } else { if (BUNappend(b, getArgReference(stk, pci, i), false) != GDK_SUCCEED) { BBPreclaim(b); b = NULL; msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } } } else { b = BATdescriptor(*getArgReference_bat(stk, pci, i)); if (b == NULL) { msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } } // check the BAT count, if it is bigger than RAPI_MAX_TUPLES, fail if (BATcount(b) > RAPI_MAX_TUPLES) { msg = createException(MAL, "rapi.eval", "Got "BUNFMT" rows, but can only handle "LLFMT". Sorry.", BATcount(b), (lng) RAPI_MAX_TUPLES); BBPunfix(b->batCacheid); goto wrapup; } varname = PROTECT(Rf_install(args[i])); varvalue = bat_to_sexp(b, bat_type); if (varvalue == NULL) { msg = createException(MAL, "rapi.eval", "unknown argument type "); goto wrapup; } BBPunfix(b->batCacheid); // install vector into R environment Rf_defineVar(varname, varvalue, env); UNPROTECT(2); } /* we are going to evaluate the user function within an anonymous function call: * ret <- (function(arg1){return(arg1*2)})(42) * the user code is put inside the {}, this keeps our environment clean (TM) and gives * a clear path for return values, namely using the builtin return() function * this is also compatible with PL/R */ pos = 0; argnames = malloc(argnameslen); if (argnames == NULL) { msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } argnames[0] = '\0'; for (i = pci->retc + 2; i < pci->argc; i++) { pos += snprintf(argnames + pos, argnameslen - pos, "%s%s", args[i], i < pci->argc - 1 ? ", " : ""); } rcalllen = 2 * pos + strlen(exprStr) + 100; rcall = malloc(rcalllen); if (rcall == NULL) { msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } snprintf(rcall, rcalllen, "ret <- as.data.frame((function(%s){%s})(%s), nm=NA, stringsAsFactors=F)\n", argnames, exprStr, argnames); free(argnames); argnames = NULL; #ifdef _RAPI_DEBUG_ printf("# R call %s\n",rcall); #endif x = R_ParseVector(mkString(rcall), 1, &status, R_NilValue); if (LENGTH(x) != 1 || status != PARSE_OK) { msg = createException(MAL, "rapi.eval", "Error parsing R expression '%s'. ", exprStr); goto wrapup; } retval = R_tryEval(VECTOR_ELT(x, 0), env, &evalErr); if (evalErr != FALSE) { char* errormsg = strdup(R_curErrorBuf()); size_t c; if (errormsg == NULL) { msg = createException(MAL, "rapi.eval", "Error running R expression."); goto wrapup; } // remove newlines from error message so it fits into a MAPI error (lol) for (c = 0; c < strlen(errormsg); c++) { if (errormsg[c] == '\r' || errormsg[c] == '\n') { errormsg[c] = ' '; } } msg = createException(MAL, "rapi.eval", "Error running R expression: %s", errormsg); free(errormsg); goto wrapup; } // ret should be a data frame with exactly as many columns as we need from retc ret_cols = LENGTH(retval); if (ret_cols != pci->retc) { msg = createException(MAL, "rapi.eval", "Expected result of %d columns, got %d", pci->retc, ret_cols); goto wrapup; } // collect the return values for (i = 0; i < pci->retc; i++) { SEXP ret_col = VECTOR_ELT(retval, i); int bat_type = getBatType(getArgType(mb,pci,i)); if (bat_type == TYPE_any || bat_type == TYPE_void) { getArgType(mb,pci,i) = bat_type; msg = createException(MAL, "rapi.eval", "Unknown return value, possibly projecting with no parameters."); goto wrapup; } // hand over the vector into a BAT b = sexp_to_bat(ret_col, bat_type); if (b == NULL) { msg = createException(MAL, "rapi.eval", "Failed to convert column %i", i); goto wrapup; } // bat return if (isaBatType(getArgType(mb,pci,i))) { *getArgReference_bat(stk, pci, i) = b->batCacheid; } else { // single value return, only for non-grouped aggregations BATiter li = bat_iterator(b); if (VALinit(&stk->stk[pci->argv[i]], bat_type, BUNtail(li, 0)) == NULL) { // TODO BUNtail here msg = createException(MAL, "rapi.eval", SQLSTATE(HY001) MAL_MALLOC_FAIL); goto wrapup; } } msg = MAL_SUCCEED; } /* unprotect environment, so it will be eaten by the GC. */ UNPROTECT(1); wrapup: MT_lock_unset(&rapiLock); if (argnames) free(argnames); if (rcall) free(rcall); for (i = 0; i < pci->argc; i++) GDKfree(args[i]); GDKfree(args); return msg; }
static str CMDbatBINARY0(MalStkPtr stk, InstrPtr pci, BAT *(*batfunc)(BAT *, BAT *, BAT *), BAT *(*batfunc1)(BAT *, const ValRecord *, BAT *), BAT *(*batfunc2)(const ValRecord *, BAT *, BAT *), const char *malfunc) { bat *bid; BAT *bn, *b, *s = NULL; int tp1, tp2; tp1 = stk->stk[getArg(pci, 1)].vtype; tp2 = stk->stk[getArg(pci, 2)].vtype; if (pci->argc == 4) { bat *sid = getArgReference_bat(stk, pci, 3); if (*sid && (s = BATdescriptor(*sid)) == NULL) throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp1 == TYPE_bat || isaBatType(tp1)) { BAT *b2 = NULL; bid = getArgReference_bat(stk, pci, 1); b = BATdescriptor(*bid); if (b == NULL) { if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } if (tp2 == TYPE_bat || isaBatType(tp2)) { bid = getArgReference_bat(stk, pci, 2); b2 = BATdescriptor(*bid); if (b2 == NULL) { BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } } if (b2) { bn = (*batfunc)(b, b2, s); BBPunfix(b2->batCacheid); } else if (batfunc1 == NULL) { BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, PROGRAM_NYI); } else { bn = (*batfunc1)(b, &stk->stk[getArg(pci, 2)], s); } } else if (batfunc2 == NULL) { throw(MAL, malfunc, PROGRAM_NYI); } else { assert(tp1 != TYPE_bat && !isaBatType(tp1)); assert(tp2 == TYPE_bat || isaBatType(tp2)); bid = getArgReference_bat(stk, pci, 2); b = BATdescriptor(*bid); if (b == NULL) { if (s) BBPunfix(s->batCacheid); throw(MAL, malfunc, SQLSTATE(HY002) RUNTIME_OBJECT_MISSING); } bn = (*batfunc2)(&stk->stk[getArg(pci, 1)], b, s); } BBPunfix(b->batCacheid); if (s) BBPunfix(s->batCacheid); if (bn == NULL) { return mythrow(MAL, malfunc, OPERATION_FAILED); } bid = getArgReference_bat(stk, pci, 0); BBPkeepref(*bid = bn->batCacheid); return MAL_SUCCEED; }