/** * svec_recv - converts external binary format to text */ Datum svec_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); SvecType *svec; SparseData sdata=makeEmptySparseData();; sdata->type_of_data = pq_getmsgint(buf, sizeof(int)); sdata->unique_value_count = pq_getmsgint(buf, sizeof(int)); sdata->total_value_count = pq_getmsgint(buf, sizeof(int)); sdata->vals->len = pq_getmsgint(buf, sizeof(int)); sdata->index->len = pq_getmsgint(buf, sizeof(int)); sdata->vals->data = (char *)pq_getmsgbytes(buf,sdata->vals->len); sdata->index->data = (char *)pq_getmsgbytes(buf,sdata->index->len); svec = svec_from_sparsedata(sdata,true); //Note this copies the data // freeSparseDataAndData(sdata); pfree(sdata); PG_RETURN_SVECTYPE_P(svec); }
Datum uuid_recv(PG_FUNCTION_ARGS) { StringInfo buffer = (StringInfo) PG_GETARG_POINTER(0); pg_uuid_t *uuid; uuid = (pg_uuid_t *) palloc(UUID_LEN); memcpy(uuid->data, pq_getmsgbytes(buffer, UUID_LEN), UUID_LEN); PG_RETURN_POINTER(uuid); }
datum_t uuid_recv(PG_FUNC_ARGS) { struct string* buffer; pg_uuid_t *uuid; buffer = (struct string*) ARG_POINTER(0); uuid = (pg_uuid_t*) palloc(UUID_LEN); memcpy(uuid->data, pq_getmsgbytes(buffer, UUID_LEN), UUID_LEN); RET_POINTER(uuid); }
Datum nseq_recv (PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER (0); int len = buf->len; const char *str = pq_getmsgbytes (buf, len); NSEQ *result = (NSEQ *) palloc0 (len); memcpy (result, str, len); PG_RETURN_POINTER (result); }
Datum molecule_recv (PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER (0); int len = buf->len; const char *str = pq_getmsgbytes (buf, len); MOLECULE *result = (MOLECULE *) palloc (len); //SET_VARSIZE (result,(buf->len + VARHDRSZ)); memset(result,0x0,len); memcpy (result, str, len); PG_RETURN_POINTER (result); }
/* * Read tuple in remote format from stream. * * The returned tuple points into the input stringinfo. */ static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple) { int i; int natts; /* Get of attributes. */ natts = pq_getmsgint(in, 2); memset(tuple->changed, 0, sizeof(tuple->changed)); /* Read the data */ for (i = 0; i < natts; i++) { char kind; int len; kind = pq_getmsgbyte(in); switch (kind) { case 'n': /* null */ tuple->values[i] = NULL; tuple->changed[i] = true; break; case 'u': /* unchanged column */ tuple->values[i] = (char *) 0xdeadbeef; /* make bad usage more obvious */ break; case 't': /* text formatted value */ { tuple->changed[i] = true; len = pq_getmsgint(in, 4); /* read length */ /* and data */ tuple->values[i] = (char *) pq_getmsgbytes(in, len); } break; default: elog(ERROR, "unknown data representation type '%c'", kind); } } }
/* * Deserialize a HeapTuple's data from a byte-array. * * This code is based on the binary input handling functions in copy.c. */ HeapTuple DeserializeTuple(SerTupInfo * pSerInfo, StringInfo serialTup) { MemoryContext oldCtxt; TupleDesc tupdesc; HeapTuple htup; int natts; SerAttrInfo *attrInfo; uint32 attr_size; int i; StringInfoData attr_data; bool fHandled; AssertArg(pSerInfo != NULL); AssertArg(serialTup != NULL); tupdesc = pSerInfo->tupdesc; natts = tupdesc->natts; /* * Flip to our tuple-serialization memory-context, to speed up memory * reclamation operations. */ AssertState(s_tupSerMemCtxt != NULL); oldCtxt = MemoryContextSwitchTo(s_tupSerMemCtxt); /* Receive nulls character-array. */ pq_copymsgbytes(serialTup, pSerInfo->nulls, natts); skipPadding(serialTup); /* Deserialize the non-NULL attributes of this tuple */ initStringInfo(&attr_data); for (i = 0; i < natts; ++i) { attrInfo = pSerInfo->myinfo + i; if (pSerInfo->nulls[i]) /* NULL field. */ { pSerInfo->values[i] = (Datum) 0; continue; } /* * Assume that the data's output will be handled by the special IO * code, and if not then we can handle it the slow way. */ fHandled = true; switch (attrInfo->atttypid) { case INT4OID: pSerInfo->values[i] = Int32GetDatum(stringInfoGetInt32(serialTup)); break; case CHAROID: pSerInfo->values[i] = CharGetDatum(pq_getmsgbyte(serialTup)); skipPadding(serialTup); break; case BPCHAROID: case VARCHAROID: case INT2VECTOROID: /* postgres serialization logic broken, use our own */ case OIDVECTOROID: /* postgres serialization logic broken, use our own */ case ANYARRAYOID: { text *pText; int textSize; textSize = stringInfoGetInt32(serialTup); #ifdef TUPSER_SCRATCH_SPACE if (textSize + VARHDRSZ <= attrInfo->varlen_scratch_size) pText = (text *) attrInfo->pv_varlen_scratch; else pText = (text *) palloc(textSize + VARHDRSZ); #else pText = (text *) palloc(textSize + VARHDRSZ); #endif SET_VARSIZE(pText, textSize + VARHDRSZ); pq_copymsgbytes(serialTup, VARDATA(pText), textSize); skipPadding(serialTup); pSerInfo->values[i] = PointerGetDatum(pText); break; } case DATEOID: { /* * TODO: I would LIKE to do something more efficient, but * DateADT is not strictly limited to 4 bytes by its * definition. */ DateADT date; pq_copymsgbytes(serialTup, (char *) &date, sizeof(DateADT)); skipPadding(serialTup); pSerInfo->values[i] = DateADTGetDatum(date); break; } case NUMERICOID: { /* * Treat the numeric as a varlena variable, and just push * the whole shebang to the output-buffer. We don't care * about the guts of the numeric. */ Numeric num; int numSize; numSize = stringInfoGetInt32(serialTup); #ifdef TUPSER_SCRATCH_SPACE if (numSize + VARHDRSZ <= attrInfo->varlen_scratch_size) num = (Numeric) attrInfo->pv_varlen_scratch; else num = (Numeric) palloc(numSize + VARHDRSZ); #else num = (Numeric) palloc(numSize + VARHDRSZ); #endif SET_VARSIZE(num, numSize + VARHDRSZ); pq_copymsgbytes(serialTup, VARDATA(num), numSize); skipPadding(serialTup); pSerInfo->values[i] = NumericGetDatum(num); break; } case ACLITEMOID: { int aclSize, k, cnt; char *inputstring, *starsfree; aclSize = stringInfoGetInt32(serialTup); inputstring = (char*) palloc(aclSize + 1); starsfree = (char*) palloc(aclSize + 1); cnt = 0; pq_copymsgbytes(serialTup, inputstring, aclSize); skipPadding(serialTup); inputstring[aclSize] = '\0'; for(k=0; k<aclSize; k++) { if( inputstring[k] != '*') { starsfree[cnt] = inputstring[k]; cnt++; } } starsfree[cnt] = '\0'; pSerInfo->values[i] = DirectFunctionCall1(aclitemin, CStringGetDatum(starsfree)); pfree(inputstring); break; } case 210: { int strsize; char *smgrstr; strsize = stringInfoGetInt32(serialTup); smgrstr = (char*) palloc(strsize + 1); pq_copymsgbytes(serialTup, smgrstr, strsize); skipPadding(serialTup); smgrstr[strsize] = '\0'; pSerInfo->values[i] = DirectFunctionCall1(smgrin, CStringGetDatum(smgrstr)); break; } default: fHandled = false; } if (fHandled) continue; attr_size = stringInfoGetInt32(serialTup); /* reset attr_data to empty, and load raw data into it */ attr_data.len = 0; attr_data.data[0] = '\0'; attr_data.cursor = 0; appendBinaryStringInfo(&attr_data, pq_getmsgbytes(serialTup, attr_size), attr_size); skipPadding(serialTup); /* Call the attribute type's binary input converter. */ if (attrInfo->recv_finfo.fn_nargs == 1) pSerInfo->values[i] = FunctionCall1(&attrInfo->recv_finfo, PointerGetDatum(&attr_data)); else if (attrInfo->recv_finfo.fn_nargs == 2) pSerInfo->values[i] = FunctionCall2(&attrInfo->recv_finfo, PointerGetDatum(&attr_data), ObjectIdGetDatum(attrInfo->recv_typio_param)); else if (attrInfo->recv_finfo.fn_nargs == 3) pSerInfo->values[i] = FunctionCall3(&attrInfo->recv_finfo, PointerGetDatum(&attr_data), ObjectIdGetDatum(attrInfo->recv_typio_param), Int32GetDatum(tupdesc->attrs[i]->atttypmod) ); else { ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("Conversion function takes %d args",attrInfo->recv_finfo.fn_nargs))); } /* Trouble if it didn't eat the whole buffer */ if (attr_data.cursor != attr_data.len) { ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("incorrect binary data format"))); } } /* * Construct the tuple from the Datums and nulls values. NOTE: Switch * out of our temporary context before we form the tuple! */ MemoryContextSwitchTo(oldCtxt); htup = heap_form_tuple(tupdesc, pSerInfo->values, pSerInfo->nulls); MemoryContextReset(s_tupSerMemCtxt); /* All done. Return the result. */ return htup; }