/* ---------------------------------------------------------------- * caql_getattr() * during beginscan/endscan iteration, get a tuple attribute for * current tuple * ---------------------------------------------------------------- */ Datum caql_getattr(cqContext *pCtx, AttrNumber attnum, bool *isnull) { Assert(HeapTupleIsValid(pCtx->cq_lasttup)); return caql_getattr_internal(pCtx, pCtx->cq_lasttup, attnum, isnull); }
Datum caql_getattr(cqContext *pCtx, AttrNumber attnum, bool *isnull) { Assert(HeapTupleIsValid(pCtx->cq_lasttup)); return caql_getattr_internal(pCtx, pCtx->cq_lasttup, attnum, isnull); /* NOTE: could this be used if caql is extended to support joins, eg what would attnum be for "SELECT * FROM pg_resqueue, pg_resqueuecapability ..." ? Potentially, the attnum is just the ordinal position of the combined SELECT list, eg you could reference pg_resqueuecapability.restypid as (Natts_pg_resqueue+Anum_pg_resourcetype_restypid). */ }
/* ---------------------------------------------------------------- * caql_getcstring_plus() * Return a cstring column from the first tuple and end the scan. * ---------------------------------------------------------------- */ char *caql_getcstring_plus(cqContext *pCtx0, int *pFetchcount, bool *pbIsNull, cq_list *pcql) { const char *caql_str = pcql->caqlStr; const char *filenam = pcql->filename; int lineno = pcql->lineno; struct caql_hash_cookie *pchn = cq_lookup(caql_str, strlen(caql_str), pcql); cqContext *pCtx; cqContext cqc; HeapTuple tuple; char *result = NULL; if (NULL == pchn) elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", caql_str, filenam, lineno); Assert(!pchn->bInsert); /* INSERT not allowed */ /* use the provided context, or provide a clean local ctx */ if (pCtx0) pCtx = pCtx0; else pCtx = cqclr(&cqc); pCtx = caql_switch(pchn, pCtx, pcql); /* NOTE: caql_switch frees the pcql */ if (pFetchcount) *pFetchcount = 0; if (pbIsNull) *pbIsNull = true; /* use the SysCache */ if (pCtx->cq_usesyscache) { tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, pCtx->cq_NumKeys, pCtx->cq_cacheKeys); } else { tuple = systable_getnext(pCtx->cq_sysScan); } if (HeapTupleIsValid(tuple)) { bool isnull; Datum d; if (pFetchcount) *pFetchcount = 1; d = caql_getattr_internal(pCtx, tuple, pchn->attnum, &isnull); if (!isnull) { switch (pchn->atttype) { case NAMEOID: result = DatumGetCString(DirectFunctionCall1(nameout, d)); break; case TEXTOID: result = DatumGetCString(DirectFunctionCall1(textout, d)); break; default: elog(ERROR, "column not a cstring: %s\nfile: %s, line %d", caql_str, filenam, lineno); } } if (pbIsNull) *pbIsNull = isnull; } /* end HeapTupleIsValid */ if (pCtx->cq_usesyscache) { if (HeapTupleIsValid(tuple)) ReleaseSysCache(tuple); } else { if (pFetchcount && HeapTupleIsValid(tuple)) { if (HeapTupleIsValid(systable_getnext(pCtx->cq_sysScan))) { *pFetchcount = 2; } } systable_endscan(pCtx->cq_sysScan); } caql_heapclose(pCtx); return (result); } /* end caql_getcstring_plus */
/* ---------------------------------------------------------------- * caql_getoid_plus() * Return an oid column from the first tuple and end the scan. * Note: this works for regproc columns as well, but you should cast * the output as RegProcedure. * ---------------------------------------------------------------- */ Oid caql_getoid_plus(cqContext *pCtx0, int *pFetchcount, bool *pbIsNull, cq_list *pcql) { const char *caql_str = pcql->caqlStr; const char *filenam = pcql->filename; int lineno = pcql->lineno; struct caql_hash_cookie *pchn = cq_lookup(caql_str, strlen(caql_str), pcql); cqContext *pCtx; cqContext cqc; HeapTuple tuple; Oid result = InvalidOid; if (NULL == pchn) elog(ERROR, "invalid caql string: %s\nfile: %s, line %d", caql_str, filenam, lineno); Assert(!pchn->bInsert); /* INSERT not allowed */ /* use the provided context, or provide a clean local ctx */ if (pCtx0) pCtx = pCtx0; else pCtx = cqclr(&cqc); pCtx = caql_switch(pchn, pCtx, pcql); /* NOTE: caql_switch frees the pcql */ if (pFetchcount) *pFetchcount = 0; if (pbIsNull) *pbIsNull = true; /* use the SysCache */ if (pCtx->cq_usesyscache) { tuple = SearchSysCacheKeyArray(pCtx->cq_cacheId, pCtx->cq_NumKeys, pCtx->cq_cacheKeys); } else { tuple = systable_getnext(pCtx->cq_sysScan); } if (HeapTupleIsValid(tuple)) { if (pFetchcount) *pFetchcount = 1; /* if attnum not set, (InvalidAttrNumber == 0) * use tuple oid, else extract oid from column * (includes ObjectIdAttributeNumber == -2) */ if (pchn->attnum <= InvalidAttrNumber) { if (pbIsNull) *pbIsNull = false; result = HeapTupleGetOid(tuple); } else /* find oid column */ { bool isnull; Datum d = caql_getattr_internal(pCtx, tuple, pchn->attnum, &isnull); if (!isnull) { switch (pchn->atttype) { case OIDOID: case REGPROCOID: result = DatumGetObjectId(d); break; default: elog(ERROR, "column not an oid: %s\nfile: %s, line %d", caql_str, filenam, lineno); } } if (pbIsNull) *pbIsNull = isnull; } } /* end HeapTupleIsValid */ if (pCtx->cq_usesyscache) { if (HeapTupleIsValid(tuple)) ReleaseSysCache(tuple); } else { if (pFetchcount && HeapTupleIsValid(tuple)) { if (HeapTupleIsValid(systable_getnext(pCtx->cq_sysScan))) { *pFetchcount = 2; } } systable_endscan(pCtx->cq_sysScan); } caql_heapclose(pCtx); return (result); } /* end caql_getoid_plus */