/* * At any point we should be able to construct an ascii representation of * the type descriptor. Including the variable references. */ str getTypeName(malType tpe) { char buf[PATHLENGTH], *s; size_t l = PATHLENGTH; int k; if (tpe == TYPE_any) return GDKstrdup("any"); if (isaBatType(tpe)) { snprintf(buf, l, "bat["); l -= strlen(buf); s = buf + strlen(buf); k = getColumnIndex(tpe); if (k) snprintf(s, l, ":any%c%d]",TMPMARKER, k); else if (getColumnType(tpe) == TYPE_any) snprintf(s, l, ":any]"); else snprintf(s, l, ":%s]", ATOMname(getColumnType(tpe))); return GDKstrdup(buf); } if (isAnyExpression(tpe)) { strncpy(buf, "any", 4); if (isAnyExpression(tpe)) snprintf(buf + 3, PATHLENGTH - 3, "%c%d", TMPMARKER, getColumnIndex(tpe)); return GDKstrdup(buf); } return GDKstrdup(ATOMname(tpe)); }
str BKCgetColumnType(str *res, const bat *bid) { const char *ret = str_nil; if (BBPcheck(*bid, "bat.getColumnType")) { BAT *b = BBPquickdesc(abs(*bid), 0); if (b) { ret = *bid < 0 ? ATOMname(b->htype) : ATOMname(b->ttype); } } *res = GDKstrdup(ret); 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 void HASHinfo(BAT *bk, BAT *bv, Hash *h, str s) { BUN i; BUN j; BUN k; BUN cnt[COLLISION + 1]; BUNappend(bk, pre(s, "type"), FALSE); BUNappend(bv, ATOMname(h->type),FALSE); BUNappend(bk, pre(s, "mask"), FALSE); BUNappend(bv, local_utoa(h->lim),FALSE); for (i = 0; i < COLLISION + 1; i++) { cnt[i] = 0; } for (i = 0; i <= h->mask; i++) { j = HASHlist(h, i); for (k = 0; j; k++) j >>= 1; cnt[k]++; } for (i = 0; i < COLLISION + 1; i++) if (cnt[i]) { BUNappend(bk, pre(s, local_utoa(i?(((size_t)1)<<(i-1)):0)), FALSE); BUNappend(bv, local_utoa((size_t) cnt[i]), FALSE); } }
static int dec_tostr(void *extra, char **Buf, int *len, int type, ptr a) { /* support dec map to bte, sht, int and lng */ if (type == TYPE_bte) { DEC_TOSTR(bte); } else if (type == TYPE_sht) { DEC_TOSTR(sht); } else if (type == TYPE_int) { DEC_TOSTR(int); } else if (type == TYPE_lng) { DEC_TOSTR(lng); } else { GDKerror("Decimal cannot be mapped to %s\n", ATOMname(type)); } return 0; }
static ssize_t numFromStr(const char *src, size_t *len, void **dst, int tp, bool external) { const char *p = src; size_t sz = ATOMsize(tp); #ifdef HAVE_HGE hge base = 0; #else lng base = 0; #endif int sign = 1; /* a valid number has the following syntax: * [-+]?[0-9]+([eE][0-9]+)?(LL)? -- PCRE syntax, or in other words * optional sign, one or more digits, optional exponent, optional LL * the exponent has the following syntax: * lower or upper case letter E, one or more digits * embedded spaces are not allowed * the optional LL at the end are only allowed for lng and hge * values */ atommem(sz); if (GDK_STRNIL(src)) { memcpy(*dst, ATOMnilptr(tp), sz); return 1; } while (GDKisspace(*p)) p++; if (!num10(*p)) { switch (*p) { case 'n': if (external) { memcpy(*dst, ATOMnilptr(tp), sz); if (p[1] == 'i' && p[2] == 'l') { p += 3; return (ssize_t) (p - src); } } GDKerror("not a number"); goto bailout; case '-': sign = -1; p++; break; case '+': p++; break; } if (!num10(*p)) { GDKerror("not a number"); goto bailout; } } do { int dig = base10(*p); if (base > maxdiv[1].maxval || (base == maxdiv[1].maxval && dig > maxmod10)) { /* overflow */ goto overflow; } base = 10 * base + dig; p++; } while (num10(*p)); if ((*p == 'e' || *p == 'E') && num10(p[1])) { p++; if (base == 0) { /* if base is 0, any exponent will do, the * result is still 0 */ while (num10(*p)) p++; } else { int exp = 0; do { /* this calculation cannot overflow */ exp = exp * 10 + base10(*p); if (exp >= (int) (sizeof(maxdiv) / sizeof(maxdiv[0]))) { /* overflow */ goto overflow; } p++; } while (num10(*p)); if (base > maxdiv[exp].maxval) { /* overflow */ goto overflow; } base *= maxdiv[exp].scale; } } base *= sign; switch (sz) { case 1: { bte **dstbte = (bte **) dst; if (base < GDK_bte_min || base > GDK_bte_max) { goto overflow; } **dstbte = (bte) base; break; } case 2: { sht **dstsht = (sht **) dst; if (base < GDK_sht_min || base > GDK_sht_max) { goto overflow; } **dstsht = (sht) base; break; } case 4: { int **dstint = (int **) dst; if (base < GDK_int_min || base > GDK_int_max) { goto overflow; } **dstint = (int) base; break; } case 8: { lng **dstlng = (lng **) dst; #ifdef HAVE_HGE if (base < GDK_lng_min || base > GDK_lng_max) { goto overflow; } #endif **dstlng = (lng) base; if (p[0] == 'L' && p[1] == 'L') p += 2; break; } #ifdef HAVE_HGE case 16: { hge **dsthge = (hge **) dst; **dsthge = (hge) base; if (p[0] == 'L' && p[1] == 'L') p += 2; break; } #endif } while (GDKisspace(*p)) p++; return (ssize_t) (p - src); overflow: while (num10(*p)) p++; GDKerror("overflow: \"%.*s\" does not fit in %s\n", (int) (p - src), src, ATOMname(tp)); bailout: memcpy(*dst, ATOMnilptr(tp), sz); return -1; }
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 {
static gdk_return CMDinfo(BAT **ret1, BAT **ret2, BAT *b) { BAT *bk, *bv; const char *mode, *accessmode; if (!(bk = BATnew(TYPE_void, TYPE_str, 128, TRANSIENT))) return GDK_FAIL; if (!(bv = BATnew(TYPE_void, TYPE_str, 128, TRANSIENT))) { BBPreclaim(bk); return GDK_FAIL; } BATseqbase(bk,0); BATseqbase(bv,0); *ret1 = bk; *ret2 = bv; if (b->batPersistence == PERSISTENT) { mode = "persistent"; } else if (b->batPersistence == TRANSIENT) { mode = "transient"; } else { mode ="unknown"; } switch (b->batRestricted) { case BAT_READ: accessmode = "read-only"; break; case BAT_WRITE: accessmode = "updatable"; break; case BAT_APPEND: accessmode = "append-only"; break; default: accessmode = "unknown"; } BUNappend(bk, "batId", FALSE); BUNappend(bv, BATgetId(b),FALSE); BUNappend(bk, "batCacheid", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->batCacheid)),FALSE); BUNappend(bk, "hparentid", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->H->heap.parentid)),FALSE); BUNappend(bk, "tparentid", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->T->heap.parentid)),FALSE); BUNappend(bk, "batSharecnt", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->batSharecnt)),FALSE); BUNappend(bk, "batCount", FALSE); BUNappend(bv, local_utoa((size_t)b->batCount),FALSE); BUNappend(bk, "batCapacity", FALSE); BUNappend(bv, local_utoa((size_t)b->batCapacity),FALSE); BUNappend(bk, "head", FALSE); BUNappend(bv, ATOMname(b->htype),FALSE); BUNappend(bk, "tail", FALSE); BUNappend(bv, ATOMname(b->ttype),FALSE); BUNappend(bk, "batPersistence", FALSE); BUNappend(bv, mode,FALSE); BUNappend(bk, "batRestricted", FALSE); BUNappend(bv, accessmode,FALSE); BUNappend(bk, "batRefcnt", FALSE); BUNappend(bv, local_itoa((ssize_t)(BBP_refs(b->batCacheid))),FALSE); BUNappend(bk, "batLRefcnt", FALSE); BUNappend(bv, local_itoa((ssize_t)(BBP_lrefs(b->batCacheid))),FALSE); BUNappend(bk, "batDirty", FALSE); BUNappend(bv, BATdirty(b) ? "dirty" : "clean",FALSE); BUNappend(bk, "hsorted", FALSE); BUNappend(bv, local_itoa((ssize_t)BAThordered(b)),FALSE); BUNappend(bk, "hrevsorted", FALSE); BUNappend(bv, local_itoa((ssize_t)BAThrevordered(b)),FALSE); BUNappend(bk, "hident", FALSE); BUNappend(bv, b->hident,FALSE); BUNappend(bk, "hdense", FALSE); BUNappend(bv, local_itoa((ssize_t)(BAThdense(b))),FALSE); BUNappend(bk, "hseqbase", FALSE); BUNappend(bv, oidtostr(b->hseqbase),FALSE); BUNappend(bk, "hkey", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->hkey)),FALSE); BUNappend(bk, "hvarsized", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->hvarsized)),FALSE); BUNappend(bk, "halign", FALSE); BUNappend(bv, local_utoa(b->halign),FALSE); BUNappend(bk, "hnosorted", FALSE); BUNappend(bv, local_utoa(b->H->nosorted),FALSE); BUNappend(bk, "hnorevsorted", FALSE); BUNappend(bv, local_utoa(b->H->norevsorted),FALSE); BUNappend(bk, "hnodense", FALSE); BUNappend(bv, local_utoa(b->H->nodense),FALSE); BUNappend(bk, "hnokey[0]", FALSE); BUNappend(bv, local_utoa(b->H->nokey[0]),FALSE); BUNappend(bk, "hnokey[1]", FALSE); BUNappend(bv, local_utoa(b->H->nokey[1]),FALSE); BUNappend(bk, "hnonil", FALSE); BUNappend(bv, local_utoa(b->H->nonil),FALSE); BUNappend(bk, "hnil", FALSE); BUNappend(bv, local_utoa(b->H->nil),FALSE); BUNappend(bk, "tident", FALSE); BUNappend(bv, b->tident,FALSE); BUNappend(bk, "tdense", FALSE); BUNappend(bv, local_itoa((ssize_t)(BATtdense(b))), FALSE); BUNappend(bk, "tseqbase", FALSE); BUNappend(bv, oidtostr(b->tseqbase), FALSE); BUNappend(bk, "tsorted", FALSE); BUNappend(bv, local_itoa((ssize_t)BATtordered(b)), FALSE); BUNappend(bk, "trevsorted", FALSE); BUNappend(bv, local_itoa((ssize_t)BATtrevordered(b)), FALSE); BUNappend(bk, "tkey", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->tkey)), FALSE); BUNappend(bk, "tvarsized", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->tvarsized)), FALSE); BUNappend(bk, "talign", FALSE); BUNappend(bv, local_utoa(b->talign), FALSE); BUNappend(bk, "tnosorted", FALSE); BUNappend(bv, local_utoa(b->T->nosorted), FALSE); BUNappend(bk, "tnorevsorted", FALSE); BUNappend(bv, local_utoa(b->T->norevsorted), FALSE); BUNappend(bk, "tnodense", FALSE); BUNappend(bv, local_utoa(b->T->nodense), FALSE); BUNappend(bk, "tnokey[0]", FALSE); BUNappend(bv, local_utoa(b->T->nokey[0]), FALSE); BUNappend(bk, "tnokey[1]", FALSE); BUNappend(bv, local_utoa(b->T->nokey[1]), FALSE); BUNappend(bk, "tnonil", FALSE); BUNappend(bv, local_utoa(b->T->nonil), FALSE); BUNappend(bk, "tnil", FALSE); BUNappend(bv, local_utoa(b->T->nil), FALSE); BUNappend(bk, "batInserted", FALSE); BUNappend(bv, local_utoa(b->batInserted), FALSE); BUNappend(bk, "batDeleted", FALSE); BUNappend(bv, local_utoa(b->batDeleted), FALSE); BUNappend(bk, "batFirst", FALSE); BUNappend(bv, local_utoa(b->batFirst), FALSE); BUNappend(bk, "htop", FALSE); BUNappend(bv, local_utoa(b->H->heap.free), FALSE); BUNappend(bk, "ttop", FALSE); BUNappend(bv, local_utoa(b->T->heap.free), FALSE); BUNappend(bk, "batStamp", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->batStamp)), FALSE); BUNappend(bk, "lastUsed", FALSE); BUNappend(bv, local_itoa((ssize_t)(BBP_lastused(b->batCacheid))), FALSE); BUNappend(bk, "curStamp", FALSE); BUNappend(bv, local_itoa((ssize_t)(BBPcurstamp())), FALSE); BUNappend(bk, "batCopiedtodisk", FALSE); BUNappend(bv, local_itoa((ssize_t)(b->batCopiedtodisk)), FALSE); BUNappend(bk, "batDirtydesc", FALSE); BUNappend(bv, b->batDirtydesc ? "dirty" : "clean", FALSE); BUNappend(bk, "H->heap.dirty", FALSE); BUNappend(bv, b->H->heap.dirty ? "dirty" : "clean", FALSE); BUNappend(bk, "T->heap.dirty", FALSE); BUNappend(bv, b->T->heap.dirty ? "dirty" : "clean", FALSE); infoHeap(bk, bv, &b->H->heap, "head."); infoHeap(bk, bv, &b->T->heap, "tail."); BUNappend(bk, "H->vheap->dirty", FALSE); BUNappend(bv, (b->H->vheap && b->H->vheap->dirty) ? "dirty" : "clean", FALSE); infoHeap(bk, bv, b->H->vheap, "hheap."); BUNappend(bk, "T->vheap->dirty", FALSE); BUNappend(bv, (b->T->vheap && b->T->vheap->dirty) ? "dirty" : "clean", FALSE); infoHeap(bk, bv, b->T->vheap, "theap."); /* dump index information */ if (b->H->hash) { HASHinfo(bk, bv, b->H->hash, "hhash->"); } if (b->T->hash) { HASHinfo(bk, bv, b->T->hash, "thash->"); } assert(BATcount(bk) == BATcount(bv)); return GDK_SUCCEED; }