boolean_t op_gvqueryget(mval *key, mval *val) { boolean_t gotit; gv_key *save_key; gvnh_reg_t *gvnh_reg; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (TREF(gv_last_subsc_null) && NEVER == gv_cur_region->null_subs) sgnl_gvnulsubsc(); switch (REG_ACC_METH(gv_cur_region)) { case dba_bg: case dba_mm: gvnh_reg = TREF(gd_targ_gvnh_reg); if (NULL == gvnh_reg) gotit = ((0 != gv_target->root) ? gvcst_queryget(val) : FALSE); /* global does not exist if root is 0 */ else INVOKE_GVCST_SPR_XXX(gvnh_reg, gotit = gvcst_spr_queryget(val)); break; case dba_cm: gotit = gvcmx_query(val); break; case dba_usr: save_key = gv_currkey; gv_currkey = gv_altkey; /* We rely on the fact that *gv_altkey area is not modified by gvusr_queryget, and don't change gv_altkey. * If and when *gv_altkey area is modified by gvusr_queryget, we have to set up a spare key area * (apart from gv_altkey and gv_currkey), and make gv_altkey point the spare area before calling gvusr_queryget */ memcpy(gv_currkey, save_key, SIZEOF(*save_key) + save_key->end); gotit = gvusr_queryget(val); gv_altkey = gv_currkey; gv_currkey = save_key; break; default: assertpro(FALSE && REG_ACC_METH(gv_cur_region)); } if (gotit) { key->mvtype = MV_STR; key->str.addr = (char *)gv_altkey->base; key->str.len = gv_altkey->end + 1; s2pool(&key->str); } else { *key = literal_null; *val = literal_null; } return gotit; }
boolean_t op_gvqueryget(mval *key, mval *val) { boolean_t gotit; gv_key *save_key; DCL_THREADGBL_ACCESS; SETUP_THREADGBL_ACCESS; if (TREF(gv_last_subsc_null) && NEVER == gv_cur_region->null_subs) sgnl_gvnulsubsc(); switch (gv_cur_region->dyn.addr->acc_meth) { case dba_bg: case dba_mm: gotit = (0 != gv_target->root) ? gvcst_queryget(val) : FALSE; break; case dba_cm: gotit = gvcmx_query(val); break; case dba_usr: save_key = gv_currkey; gv_currkey = gv_altkey; /* We rely on the fact that *gv_altkey area is not modified by gvusr_queryget, and don't change gv_altkey. * If and when *gv_altkey area is modified by gvusr_queryget, we have to set up a spare key area * (apart from gv_altkey and gv_currkey), and make gv_altkey point the spare area before calling gvusr_queryget */ memcpy(gv_currkey, save_key, SIZEOF(*save_key) + save_key->end); gotit = gvusr_queryget(val); gv_altkey = gv_currkey; gv_currkey = save_key; break; default: GTMASSERT; } if (gotit) { key->mvtype = MV_STR; key->str.addr = (char *)gv_altkey->base; key->str.len = gv_altkey->end + 1; s2pool(&key->str); } else { *key = literal_null; *val = literal_null; } return gotit; }
void op_gvquery (mval *v) { int4 size; unsigned char buff[MAX_ZWR_KEY_SZ], *end, *glob_begin; bool found; enum db_acc_method acc_meth; unsigned char *extnamsrc, *extnamdst, *extnamtop; int maxlen; char extnamdelim[] = "^|\"\"|"; mval val; /* We want to turn QUERY into QUERYGET for all types of access methods so that we can cache the value of the key returned * by $QUERY. The value is very likely to be used shortly after $QUERY - Vinaya, Aug 13, 2001 */ acc_meth = gv_cur_region->dyn.addr->acc_meth; if (gv_curr_subsc_null) { if (0 == gv_cur_region->std_null_coll) gv_currkey->base[gv_currkey->prev] = 01; else { gv_currkey->base[gv_currkey->end++]= 1; gv_currkey->base[gv_currkey->end++] = 0; gv_currkey->base[gv_currkey->end] = 0; } } else { /* Note, gv_currkey->prev isn't changed here. We rely on this in gtcmtr_query to distinguish different forms of the key */ gv_currkey->base[gv_currkey->end++]= 1; gv_currkey->base[gv_currkey->end++] = 0; gv_currkey->base[gv_currkey->end] = 0; } switch (acc_meth) { case dba_bg: case dba_mm: found = ((0 != gv_target->root) ? gvcst_query() : FALSE); /* global does not exist if root is 0 */ break; case dba_cm: found = gvcmx_query(&val); /* val ignored currently - Vinaya Aug 13, 2001*/ break; case dba_usr: found = gvusr_query(v); /* $Q result in v for dba_usr, for others, in gv_altkey */ break; default: assert(FALSE); /* why didn't we cover all access methods? */ found = FALSE; break; } v->mvtype = MV_STR; if (found) { if (acc_meth != dba_usr) { if ((end = format_targ_key(&buff[0], MAX_ZWR_KEY_SZ, gv_altkey, TRUE)) == 0) end = &buff[MAX_ZWR_KEY_SZ - 1]; size = (int)(end - &buff[0] - 1); /* exclude ^ */ glob_begin = &buff[1]; /* skip ^ */ } else { size = v->str.len - 1; /* exclude ^ */ glob_begin = (unsigned char *)v->str.addr + 1; /* skip ^ */ } /* Need to return a double-quote for every single-quote; assume worst case. */ /* Account for ^ in both cases - extnam and no extnam */ maxlen = size + ((0 == extnam_str.len) ? 1 : ((extnam_str.len * 2) + (int)(STR_LIT_LEN(extnamdelim)))); if ((stringpool.top - stringpool.free) < maxlen) { v->str.len = 0; /* so stp_gcol ignores otherwise incompletely setup mval */ stp_gcol(maxlen); } extnamdst = stringpool.free; *extnamdst++ = extnamdelim[0]; if (extnam_str.len > 0) { *extnamdst++ = extnamdelim[1]; *extnamdst++ = extnamdelim[2]; for (extnamsrc = (unsigned char *)extnam_str.addr, extnamtop = extnamsrc + extnam_str.len; extnamsrc < extnamtop; ) { *extnamdst++ = *extnamsrc; if ('"' == *extnamsrc++) /* caution : pointer increment side-effect */ *extnamdst++ = '"'; } *extnamdst++ = extnamdelim[3]; *extnamdst++ = extnamdelim[4]; extnam_str.len = 0; } memcpy(extnamdst, glob_begin, size); v->str.len = INTCAST(extnamdst - stringpool.free + size); v->str.addr = (char *)stringpool.free; stringpool.free += v->str.len; assert (v->str.addr < (char *)stringpool.top && v->str.addr >= (char *)stringpool.base); assert (v->str.addr + v->str.len <= (char *)stringpool.top && v->str.addr + v->str.len >= (char *)stringpool.base); } else /* !found */ v->str.len = 0; return; }