/* * gpxloglocsend - converts xlog location to binary format */ Datum gpxloglocsend(PG_FUNCTION_ARGS) { XLogRecPtr *xlogLoc = PG_GETARG_XLOGLOC(0); uint32 send_xlogid; uint32 send_xrecoff; StringInfoData buf; send_xlogid = xlogLoc->xlogid; send_xrecoff = xlogLoc->xrecoff; pq_begintypsend(&buf); pq_sendint(&buf, send_xlogid, sizeof(send_xlogid)); pq_sendint(&buf, send_xrecoff, sizeof(send_xrecoff)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/** * svec_send - converts text to binary format */ Datum svec_send(PG_FUNCTION_ARGS) { StringInfoData buf; SvecType *svec = PG_GETARG_SVECTYPE_P(0); SparseData sdata = sdata_from_svec(svec); pq_begintypsend(&buf); pq_sendint(&buf,sdata->type_of_data,sizeof(Oid)); pq_sendint(&buf,sdata->unique_value_count,sizeof(int)); pq_sendint(&buf,sdata->total_value_count,sizeof(int)); pq_sendint(&buf,sdata->vals->len,sizeof(int)); pq_sendint(&buf,sdata->index->len,sizeof(int)); pq_sendbytes(&buf,sdata->vals->data,sdata->vals->len); pq_sendbytes(&buf,sdata->index->data,sdata->index->len); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum rotation3d_send(PG_FUNCTION_ARGS) { Rotation3D * rotation3d = (Rotation3D*)PG_GETARG_POINTER(0); StringInfoData buf; pq_begintypsend(&buf); pq_sendfloat8(&buf, rotation3d->r11); pq_sendfloat8(&buf, rotation3d->r12); pq_sendfloat8(&buf, rotation3d->r13); pq_sendfloat8(&buf, rotation3d->r21); pq_sendfloat8(&buf, rotation3d->r22); pq_sendfloat8(&buf, rotation3d->r23); pq_sendfloat8(&buf, rotation3d->r31); pq_sendfloat8(&buf, rotation3d->r32); pq_sendfloat8(&buf, rotation3d->r33); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * tidsend - converts tid to binary format */ Datum tidsend(PG_FUNCTION_ARGS) { ItemPointer itemPtr = PG_GETARG_ITEMPOINTER(0); BlockId blockId; BlockNumber blockNumber; OffsetNumber offsetNumber; StringInfoData buf; blockId = &(itemPtr->ip_blkid); blockNumber = BlockIdGetBlockNumber(blockId); offsetNumber = itemPtr->ip_posid; pq_begintypsend(&buf); pq_sendint(&buf, blockNumber, sizeof(blockNumber)); pq_sendint(&buf, offsetNumber, sizeof(offsetNumber)); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * jsonb type send function * * Just send jsonb as a version number, then a string of text */ Datum jsonb_send(PG_FUNCTION_ARGS) { Jsonb *jb = PG_GETARG_JSONB(0); StringInfoData buf; StringInfo jtext = makeStringInfo(); int version = 1; (void) JsonbToCString(jtext, VARDATA(jb), VARSIZE(jb)); pq_begintypsend(&buf); pq_sendint(&buf, version, 1); pq_sendtext(&buf, jtext->data, jtext->len); pfree(jtext->data); pfree(jtext); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum UDT_send(UDT udt, PG_FUNCTION_ARGS) { StringInfoData buf; int32 dataLen = Type_getLength((Type)udt); if(!UDT_isScalar(udt)) ereport(ERROR, ( errcode(ERRCODE_CANNOT_COERCE), errmsg("UDT with Oid %d is not scalar", Type_getOid((Type)udt)))); if(dataLen == -1) return byteasend(fcinfo); if(dataLen == -2) return unknownsend(fcinfo); pq_begintypsend(&buf); appendBinaryStringInfo(&buf, PG_GETARG_POINTER(0), dataLen); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum tsvectorsend(PG_FUNCTION_ARGS) { TSVector vec = PG_GETARG_TSVECTOR(0); StringInfoData buf; int i, j; WordEntry *weptr = ARRPTR(vec); pq_begintypsend(&buf); pq_sendint(&buf, vec->size, sizeof(int32)); for (i = 0; i < vec->size; i++) { uint16 npos; /* * the strings in the TSVector array are not null-terminated, so we * have to send the null-terminator separately */ pq_sendtext(&buf, STRPTR(vec) + weptr->pos, weptr->len); pq_sendbyte(&buf, '\0'); npos = POSDATALEN(vec, weptr); pq_sendint(&buf, npos, sizeof(uint16)); if (npos > 0) { WordEntryPos *wepptr = POSDATAPTR(vec, weptr); for (j = 0; j < npos; j++) pq_sendint(&buf, wepptr[j], sizeof(WordEntryPos)); } weptr++; } PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
Datum enum_send(PG_FUNCTION_ARGS) { Oid enumval = PG_GETARG_OID(0); StringInfoData buf; HeapTuple tup; Form_pg_enum en; tup = SearchSysCache1(ENUMOID, ObjectIdGetDatum(enumval)); if (!HeapTupleIsValid(tup)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid internal value for enum: %u", enumval))); en = (Form_pg_enum) GETSTRUCT(tup); pq_begintypsend(&buf); pq_sendtext(&buf, NameStr(en->enumlabel), strlen(NameStr(en->enumlabel))); ReleaseSysCache(tup); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }
/* * record_send - binary output routine for any composite type. */ Datum record_send(PG_FUNCTION_ARGS) { HeapTupleHeader rec = PG_GETARG_HEAPTUPLEHEADER(0); Oid tupType; int32 tupTypmod; TupleDesc tupdesc; HeapTupleData tuple; RecordIOData *my_extra; int ncolumns; int validcols; int i; Datum *values; bool *nulls; StringInfoData buf; /* Extract type info from the tuple itself */ tupType = HeapTupleHeaderGetTypeId(rec); tupTypmod = HeapTupleHeaderGetTypMod(rec); tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod); ncolumns = tupdesc->natts; /* Build a temporary HeapTuple control structure */ tuple.t_len = HeapTupleHeaderGetDatumLength(rec); ItemPointerSetInvalid(&(tuple.t_self)); tuple.t_tableOid = InvalidOid; tuple.t_data = rec; /* * We arrange to look up the needed I/O info just once per series of * calls, assuming the record type doesn't change underneath us. */ my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra; if (my_extra == NULL || my_extra->ncolumns != ncolumns) { fcinfo->flinfo->fn_extra = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(RecordIOData) - sizeof(ColumnIOData) + ncolumns * sizeof(ColumnIOData)); my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra; my_extra->record_type = InvalidOid; my_extra->record_typmod = 0; } if (my_extra->record_type != tupType || my_extra->record_typmod != tupTypmod) { MemSet(my_extra, 0, sizeof(RecordIOData) - sizeof(ColumnIOData) + ncolumns * sizeof(ColumnIOData)); my_extra->record_type = tupType; my_extra->record_typmod = tupTypmod; my_extra->ncolumns = ncolumns; } values = (Datum *) palloc(ncolumns * sizeof(Datum)); nulls = (bool *) palloc(ncolumns * sizeof(bool)); /* Break down the tuple into fields */ heap_deform_tuple(&tuple, tupdesc, values, nulls); /* And build the result string */ pq_begintypsend(&buf); /* Need to scan to count nondeleted columns */ validcols = 0; for (i = 0; i < ncolumns; i++) { if (!tupdesc->attrs[i]->attisdropped) validcols++; } pq_sendint(&buf, validcols, 4); for (i = 0; i < ncolumns; i++) { ColumnIOData *column_info = &my_extra->columns[i]; Oid column_type = tupdesc->attrs[i]->atttypid; bytea *outputbytes; /* Ignore dropped columns in datatype */ if (tupdesc->attrs[i]->attisdropped) continue; pq_sendint(&buf, column_type, sizeof(Oid)); if (nulls[i]) { /* emit -1 data length to signify a NULL */ pq_sendint(&buf, -1, 4); continue; } /* * Convert the column value to binary */ if (column_info->column_type != column_type) { bool typIsVarlena; getTypeBinaryOutputInfo(column_type, &column_info->typiofunc, &typIsVarlena); fmgr_info_cxt(column_info->typiofunc, &column_info->proc, fcinfo->flinfo->fn_mcxt); column_info->column_type = column_type; } outputbytes = SendFunctionCall(&column_info->proc, values[i]); /* We assume the result will not have been toasted */ pq_sendint(&buf, VARSIZE(outputbytes) - VARHDRSZ, 4); pq_sendbytes(&buf, VARDATA(outputbytes), VARSIZE(outputbytes) - VARHDRSZ); pfree(outputbytes); } pfree(values); pfree(nulls); ReleaseTupleDesc(tupdesc); PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); }