Datum hstore_out(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int buflen, i; int count = HS_COUNT(in); char *out, *ptr; char *base = STRPTR(in); HEntry *entries = ARRPTR(in); if (count == 0) PG_RETURN_CSTRING(pstrdup("")); buflen = 0; /* * this loop overestimates due to pessimistic assumptions about escaping, * so very large hstore values can't be output. this could be fixed, but * many other data types probably have the same issue. This replaced code * that used the original varlena size for calculations, which was wrong * in some subtle ways. */ for (i = 0; i < count; i++) { /* include "" and => and comma-space */ buflen += 6 + 2 * HS_KEYLEN(entries, i); /* include "" only if nonnull */ buflen += 2 + (HS_VALISNULL(entries, i) ? 2 : 2 * HS_VALLEN(entries, i)); } out = ptr = palloc(buflen); for (i = 0; i < count; i++) { *ptr++ = '"'; ptr = cpw(ptr, HS_KEY(entries, base, i), HS_KEYLEN(entries, i)); *ptr++ = '"'; *ptr++ = '='; *ptr++ = '>'; if (HS_VALISNULL(entries, i)) { *ptr++ = 'N'; *ptr++ = 'U'; *ptr++ = 'L'; *ptr++ = 'L'; } else { *ptr++ = '"'; ptr = cpw(ptr, HS_VAL(entries, base, i), HS_VALLEN(entries, i)); *ptr++ = '"'; } if (i + 1 != count) { *ptr++ = ','; *ptr++ = ' '; } } *ptr = '\0'; PG_RETURN_CSTRING(out); }
Datum country_out(PG_FUNCTION_ARGS) { country c = PG_GETARG_UINT8(0); PG_RETURN_CSTRING(country_to_str(c)); }
/* * regoperout - converts operator OID to "opr_name" */ Datum regoperout(PG_FUNCTION_ARGS) { Oid oprid = PG_GETARG_OID(0); char *result; HeapTuple opertup; if (oprid == InvalidOid) { result = pstrdup("0"); PG_RETURN_CSTRING(result); } opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(oprid)); if (HeapTupleIsValid(opertup)) { Form_pg_operator operform = (Form_pg_operator) GETSTRUCT(opertup); char *oprname = NameStr(operform->oprname); /* * In bootstrap mode, skip the fancy namespace stuff and just return * the oper name. (This path is only needed for debugging output * anyway.) */ if (IsBootstrapProcessingMode()) result = pstrdup(oprname); else { FuncCandidateList clist; /* * Would this oper be found (uniquely!) by regoperin? If not, * qualify it. */ clist = OpernameGetCandidates(list_make1(makeString(oprname)), '\0', false); if (clist != NULL && clist->next == NULL && clist->oid == oprid) result = pstrdup(oprname); else { const char *nspname; nspname = get_namespace_name(operform->oprnamespace); nspname = quote_identifier(nspname); result = (char *) palloc(strlen(nspname) + strlen(oprname) + 2); sprintf(result, "%s.%s", nspname, oprname); } } ReleaseSysCache(opertup); } else { /* * If OID doesn't match any pg_operator entry, return it numerically */ result = (char *) palloc(NAMEDATALEN); snprintf(result, NAMEDATALEN, "%u", oprid); } PG_RETURN_CSTRING(result); }
Datum hstore_out(PG_FUNCTION_ARGS) { HStore *in = PG_GETARG_HS(0); int buflen, i, nnulls = 0; char *out, *ptr; char *base = STRPTR(in); HEntry *entries = ARRPTR(in); if (in->size == 0) { out = palloc(1); *out = '\0'; PG_FREE_IF_COPY(in, 0); PG_RETURN_CSTRING(out); } for (i = 0; i < in->size; i++) if (entries[i].valisnull) nnulls++; buflen = (4 /* " */ + 2 /* => */ ) * (in->size - nnulls) + (2 /* " */ + 2 /* => */ + 4 /* NULL */ ) * nnulls + 2 /* , */ * (in->size - 1) + 2 /* esc */ * (VARSIZE(in) - CALCDATASIZE(in->size, 0)) + 1 /* \0 */ ; out = ptr = palloc(buflen); for (i = 0; i < in->size; i++) { *ptr++ = '"'; ptr = cpw(ptr, base + entries[i].pos, entries[i].keylen); *ptr++ = '"'; *ptr++ = '='; *ptr++ = '>'; if (entries[i].valisnull) { *ptr++ = 'N'; *ptr++ = 'U'; *ptr++ = 'L'; *ptr++ = 'L'; } else { *ptr++ = '"'; ptr = cpw(ptr, base + entries[i].pos + entries[i].keylen, entries[i].vallen); *ptr++ = '"'; } if (i + 1 != in->size) { *ptr++ = ','; *ptr++ = ' '; } } *ptr = '\0'; PG_FREE_IF_COPY(in, 0); PG_RETURN_CSTRING(out); }
/* cash_out() * Function to convert cash to a dollars and cents representation. * XXX HACK This code appears to assume US conventions for * positive-valued amounts. - tgl 97/04/14 */ Datum cash_out(PG_FUNCTION_ARGS) { Cash value = PG_GETARG_CASH(0); char *result; char buf[CASH_BUFSZ]; int minus = 0; int count = LAST_DIGIT; int point_pos; int ssymbol_position = 0; int points, mon_group; char ssymbol; const char *csymbol, *nsymbol; char dsymbol; char convention; struct lconv *lconvert = PGLC_localeconv(); /* see comments about frac_digits in cash_in() */ points = lconvert->frac_digits; if (points < 0 || points > 10) points = 2; /* best guess in this case, I think */ /* * As with frac_digits, must apply a range check to mon_grouping to avoid * being fooled by variant CHAR_MAX values. */ mon_group = *lconvert->mon_grouping; if (mon_group <= 0 || mon_group > 6) mon_group = 3; convention = lconvert->n_sign_posn; dsymbol = ((*lconvert->mon_decimal_point != '\0') ? *lconvert->mon_decimal_point : '.'); if (*lconvert->mon_thousands_sep != '\0') ssymbol = *lconvert->mon_thousands_sep; else /* ssymbol should not equal dsymbol */ ssymbol = (dsymbol != ',') ? ',' : '.'; csymbol = ((*lconvert->currency_symbol != '\0') ? lconvert->currency_symbol : "$"); nsymbol = ((*lconvert->negative_sign != '\0') ? lconvert->negative_sign : "-"); point_pos = LAST_DIGIT - points; point_pos -= (points - 1) / mon_group; ssymbol_position = point_pos % (mon_group + 1); /* we work with positive amounts and add the minus sign at the end */ if (value < 0) { minus = 1; value = -value; } /* allow for trailing negative strings */ MemSet(buf, ' ', CASH_BUFSZ); buf[TERMINATOR] = buf[LAST_PAREN] = '\0'; while (value || count > (point_pos - 2)) { if (points && count == point_pos) buf[count--] = dsymbol; else if (ssymbol && count % (mon_group + 1) == ssymbol_position) buf[count--] = ssymbol; buf[count--] = ((uint64) value % 10) + '0'; value = ((uint64) value) / 10; } strncpy((buf + count - strlen(csymbol) + 1), csymbol, strlen(csymbol)); count -= strlen(csymbol) - 1; /* * If points == 0 and the number of digits % mon_group == 0, the code * above adds a trailing ssymbol on the far right, so remove it. */ if (buf[LAST_DIGIT] == ssymbol) buf[LAST_DIGIT] = '\0'; /* see if we need to signify negative amount */ if (minus) { result = palloc(CASH_BUFSZ + 2 - count + strlen(nsymbol)); /* Position code of 0 means use parens */ if (convention == 0) sprintf(result, "(%s)", buf + count); else if (convention == 2) sprintf(result, "%s%s", buf + count, nsymbol); else sprintf(result, "%s%s", nsymbol, buf + count); } else { result = palloc(CASH_BUFSZ + 2 - count); strcpy(result, buf + count); } PG_RETURN_CSTRING(result); }
/* * void_out - output routine for pseudo-type VOID. * * We allow this so that "SELECT function_returning_void(...)" works. */ Datum void_out(PG_FUNCTION_ARGS) { PG_RETURN_CSTRING(pstrdup("")); }