Datum frequent_strings_sketch_get_result()

in src/frequent_strings_sketch_pg_functions.c [212:277]


Datum frequent_strings_sketch_get_result(PG_FUNCTION_ARGS, bool no_false_positives) {
  FuncCallContext* funcctx;
  TupleDesc tupdesc;
  const bytea* bytes_in;
  void* sketchptr;
  unsigned long long threshold;

  if (SRF_IS_FIRSTCALL()) {
    MemoryContext oldcontext;
    funcctx = SRF_FIRSTCALL_INIT();
    oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
      ereport(
        ERROR,
        (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context that cannot accept type record"))
      );
    }

    if (PG_ARGISNULL(0)) SRF_RETURN_DONE(funcctx);
    bytes_in = PG_GETARG_BYTEA_P(0);
    sketchptr = frequent_strings_sketch_deserialize(VARDATA(bytes_in), VARSIZE(bytes_in) - VARHDRSZ);
    threshold = PG_NARGS() > 1 ? PG_GETARG_INT64(1) : 0;

    funcctx->user_fctx = frequent_strings_sketch_get_frequent_items(sketchptr, no_false_positives, threshold);
    funcctx->max_calls = ((struct frequent_strings_sketch_result*) funcctx->user_fctx)->num;
    funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);

    frequent_strings_sketch_delete(sketchptr);

    MemoryContextSwitchTo(oldcontext);
  }

  funcctx = SRF_PERCALL_SETUP();

  if (funcctx->call_cntr < funcctx->max_calls) {
    char       **values;
    HeapTuple    tuple;
    Datum        result;

    struct frequent_strings_sketch_result* frequent_strings = funcctx->user_fctx;
    struct frequent_strings_sketch_result_row* row = &frequent_strings->rows[funcctx->call_cntr];

    values = (char**) palloc(4 * sizeof(char*));
    values[0] = row->str;
    values[1] = (char*) palloc(21);
    values[2] = (char*) palloc(21);
    values[3] = (char*) palloc(21);

    snprintf(values[1], 21, "%llu", row->estimate);
    snprintf(values[2], 21, "%llu", row->lower_bound);
    snprintf(values[3], 21, "%llu", row->upper_bound);

    tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);

    result = HeapTupleGetDatum(tuple);

    pfree(values[1]);
    pfree(values[2]);
    pfree(values[3]);
    pfree(values);

    SRF_RETURN_NEXT(funcctx, result);
  } else {
    SRF_RETURN_DONE(funcctx);
  }
}