/* * tintervalrecv - converts external binary format to tinterval */ Datum tintervalrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TimeInterval tinterval; int32 status; tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData)); tinterval->status = pq_getmsgint(buf, sizeof(tinterval->status)); tinterval->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0])); tinterval->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1])); if (tinterval->data[0] == INVALID_ABSTIME || tinterval->data[1] == INVALID_ABSTIME) status = T_INTERVAL_INVAL; /* undefined */ else status = T_INTERVAL_VALID; if (status != tinterval->status) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid status in external \"tinterval\" value"))); PG_RETURN_TIMEINTERVAL(tinterval); }
Datum hstore_recv(PG_FUNCTION_ARGS) { int32 buflen; HStore *out; Pairs *pairs; int32 i; int32 pcount; StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); pcount = pq_getmsgint(buf, 4); if (pcount == 0) { out = hstorePairs(NULL, 0, 0); PG_RETURN_POINTER(out); } if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("number of pairs (%d) exceeds the maximum allowed (%d)", pcount, (int) (MaxAllocSize / sizeof(Pairs))))); pairs = palloc(pcount * sizeof(Pairs)); for (i = 0; i < pcount; ++i) { int rawlen = pq_getmsgint(buf, 4); int len; if (rawlen < 0) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("null value not allowed for hstore key"))); pairs[i].key = pq_getmsgtext(buf, rawlen, &len); pairs[i].keylen = hstoreCheckKeyLen(len); pairs[i].needfree = true; rawlen = pq_getmsgint(buf, 4); if (rawlen < 0) { pairs[i].val = NULL; pairs[i].vallen = 0; pairs[i].isnull = true; } else { pairs[i].val = pq_getmsgtext(buf, rawlen, &len); pairs[i].vallen = hstoreCheckValLen(len); pairs[i].isnull = false; } } pcount = hstoreUniquePairs(pairs, pcount, &buflen); out = hstorePairs(pairs, pcount, buflen); PG_RETURN_POINTER(out); }
/* * xidrecv - converts external binary format to xid */ Datum xidrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_TRANSACTIONID((TransactionId) pq_getmsgint(buf, sizeof(TransactionId))); }
/* * int2recv - converts external binary format to int2 */ datum_t int2recv(PG_FUNC_ARGS) { struct string* buf; buf = (struct string*) ARG_POINTER(0); RET_INT16((int16) pq_getmsgint(buf, sizeof(int16))); }
/* * cash_recv - converts external binary format to cash */ Datum cash_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_CASH((Cash) pq_getmsgint(buf, sizeof(Cash))); }
/* * oidrecv - converts external binary format to oid */ Datum oidrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid))); }
/* * cidrecv - converts external binary format to cid */ Datum cidrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_COMMANDID((CommandId) pq_getmsgint(buf, sizeof(CommandId))); }
/* * int2recv - converts external binary format to int2 */ Datum int2recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16))); }
/* * reltimerecv - converts external binary format to reltime */ Datum reltimerecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_RELATIVETIME((RelativeTime) pq_getmsgint(buf, sizeof(RelativeTime))); }
/* * abstimerecv - converts external binary format to abstime */ Datum abstimerecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); PG_RETURN_ABSOLUTETIME((AbsoluteTime) pq_getmsgint(buf, sizeof(AbsoluteTime))); }
/* * 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 number 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; kind = pq_getmsgbyte(in); switch (kind) { case 'n': /* null */ tuple->values[i] = NULL; tuple->changed[i] = true; break; case 'u': /* unchanged column */ /* we don't receive the value of an unchanged column */ tuple->values[i] = NULL; break; case 't': /* text formatted value */ { int len; tuple->changed[i] = true; len = pq_getmsgint(in, 4); /* read length */ /* and data */ tuple->values[i] = palloc(len + 1); pq_copymsgbytes(in, tuple->values[i], len); tuple->values[i][len] = '\0'; } break; default: elog(ERROR, "unrecognized data representation type '%c'", kind); } } }
/* * tidrecv - converts external binary format to tid */ Datum tidrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); ItemPointer result; BlockNumber blockNumber; OffsetNumber offsetNumber; blockNumber = pq_getmsgint(buf, sizeof(blockNumber)); offsetNumber = pq_getmsgint(buf, sizeof(offsetNumber)); result = (ItemPointer) palloc(sizeof(ItemPointerData)); ItemPointerSet(result, blockNumber, offsetNumber); PG_RETURN_ITEMPOINTER(result); }
/* * Read type info from the output stream. */ void logicalrep_read_typ(StringInfo in, LogicalRepTyp *ltyp) { ltyp->remoteid = pq_getmsgint(in, 4); /* Read type name from stream */ ltyp->nspname = pstrdup(logicalrep_read_namespace(in)); ltyp->typname = pstrdup(pq_getmsgstring(in)); }
/* * gpxloglocrecv - converts external binary format to xlog location */ Datum gpxloglocrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); XLogRecPtr *result; uint32 result_xlogid; uint32 result_xrecoff; result_xlogid = pq_getmsgint(buf, sizeof(result_xlogid)); result_xrecoff = pq_getmsgint(buf, sizeof(result_xrecoff)); result = (XLogRecPtr*) palloc(sizeof(XLogRecPtr)); result->xlogid = result_xlogid; result->xrecoff = result_xrecoff; PG_RETURN_XLOGLOC(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); } } }
/** * 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); }
/* * Read transaction BEGIN from the stream. */ void logicalrep_read_begin(StringInfo in, LogicalRepBeginData *begin_data) { /* read fields */ begin_data->final_lsn = pq_getmsgint64(in); if (begin_data->final_lsn == InvalidXLogRecPtr) elog(ERROR, "final_lsn not set in begin message"); begin_data->committime = pq_getmsgint64(in); begin_data->xid = pq_getmsgint(in, 4); }
/* * oidvectorrecv - converts external binary format to oidvector */ Datum oidvectorrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); Oid *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS])); int slot; for (slot = 0; slot < INDEX_MAX_KEYS; slot++) result[slot] = (Oid) pq_getmsgint(buf, sizeof(Oid)); PG_RETURN_POINTER(result); }
/* * txid_snapshot_recv(internal) returns txid_snapshot * * binary input function for type txid_snapshot * * format: int4 nxip, int8 xmin, int8 xmax, int8 xip */ Datum txid_snapshot_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TxidSnapshot *snap; txid last = 0; int nxip; int i; txid xmin, xmax; /* load and validate nxip */ nxip = pq_getmsgint(buf, 4); if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP) goto bad_format; xmin = pq_getmsgint64(buf); xmax = pq_getmsgint64(buf); if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID) goto bad_format; snap = palloc(TXID_SNAPSHOT_SIZE(nxip)); snap->xmin = xmin; snap->xmax = xmax; for (i = 0; i < nxip; i++) { txid cur = pq_getmsgint64(buf); if (cur < last || cur < xmin || cur >= xmax) goto bad_format; /* skip duplicate xips */ if (cur == last) { i--; nxip--; continue; } snap->xip[i] = cur; last = cur; } snap->nxip = nxip; SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip)); PG_RETURN_POINTER(snap); bad_format: ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid external txid_snapshot data"))); PG_RETURN_POINTER(NULL); /* keep compiler quiet */ }
/* * tintervalrecv - converts external binary format to tinterval */ Datum tintervalrecv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TimeInterval tinterval; tinterval = (TimeInterval) palloc(sizeof(TimeIntervalData)); tinterval->status = pq_getmsgint(buf, sizeof(tinterval->status)); if (!(tinterval->status == T_INTERVAL_INVAL || tinterval->status == T_INTERVAL_VALID)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid status in external \"tinterval\" value"), errOmitLocation(true))); tinterval->data[0] = pq_getmsgint(buf, sizeof(tinterval->data[0])); tinterval->data[1] = pq_getmsgint(buf, sizeof(tinterval->data[1])); PG_RETURN_TIMEINTERVAL(tinterval); }
/* * txid_snapshot_recv(internal) returns txid_snapshot * * binary input function for type txid_snapshot * * format: int4 nxip, int8 xmin, int8 xmax, int8 xip */ Datum txid_snapshot_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TxidSnapshot *snap; txid last = 0; int nxip; int i; txid xmin, xmax; /* load and validate nxip */ nxip = pq_getmsgint(buf, 4); if (nxip < 0 || nxip > TXID_SNAPSHOT_MAX_NXIP) goto bad_format; xmin = pq_getmsgint64(buf); xmax = pq_getmsgint64(buf); if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID) goto bad_format; snap = static_cast<TxidSnapshot *>(palloc(TXID_SNAPSHOT_SIZE(nxip))); snap->xmin = xmin; snap->xmax = xmax; for (i = 0; i < nxip; i++) { txid cur = pq_getmsgint64(buf); if (cur < last || cur < xmin || cur >= xmax) goto bad_format; /* skip duplicate xips */ if (cur == last) { i--; nxip--; continue; } snap->xip[i] = cur; last = cur; } snap->nxip = nxip; SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip)); PG_RETURN_POINTER(snap); bad_format: elog(ERROR, "invalid snapshot data"); return (Datum) NULL; }
/* * Read relation attribute names from the stream. */ static void logicalrep_read_attrs(StringInfo in, LogicalRepRelation *rel) { int i; int natts; char **attnames; Oid *atttyps; Bitmapset *attkeys = NULL; natts = pq_getmsgint(in, 2); attnames = palloc(natts * sizeof(char *)); atttyps = palloc(natts * sizeof(Oid)); /* read the attributes */ for (i = 0; i < natts; i++) { uint8 flags; /* Check for replica identity column */ flags = pq_getmsgbyte(in); if (flags & LOGICALREP_IS_REPLICA_IDENTITY) attkeys = bms_add_member(attkeys, i); /* attribute name */ attnames[i] = pstrdup(pq_getmsgstring(in)); /* attribute type id */ atttyps[i] = (Oid) pq_getmsgint(in, 4); /* we ignore attribute mode for now */ (void) pq_getmsgint(in, 4); } rel->attnames = attnames; rel->atttyps = atttyps; rel->attkeys = attkeys; rel->natts = natts; }
/* * txid_snapshot_recv(internal) returns txid_snapshot * * binary input function for type txid_snapshot * * format: int4 nxip, int8 xmin, int8 xmax, int8 xip */ Datum txid_snapshot_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); TxidSnapshot *snap; txid last = 0; int nxip; int i; int avail; int expect; txid xmin, xmax; /* * load nxip and check for nonsense. * * (nxip > avail) check is against int overflows in 'expect'. */ nxip = pq_getmsgint(buf, 4); avail = buf->len - buf->cursor; expect = 8 + 8 + nxip * 8; if (nxip < 0 || nxip > avail || expect > avail) goto bad_format; xmin = pq_getmsgint64(buf); xmax = pq_getmsgint64(buf); if (xmin == 0 || xmax == 0 || xmin > xmax || xmax > MAX_TXID) goto bad_format; snap = palloc(TXID_SNAPSHOT_SIZE(nxip)); snap->xmin = xmin; snap->xmax = xmax; snap->nxip = nxip; SET_VARSIZE(snap, TXID_SNAPSHOT_SIZE(nxip)); for (i = 0; i < nxip; i++) { txid cur = pq_getmsgint64(buf); if (cur <= last || cur < xmin || cur >= xmax) goto bad_format; snap->xip[i] = cur; last = cur; } PG_RETURN_POINTER(snap); bad_format: elog(ERROR, "invalid snapshot data"); return (Datum) NULL; }
/* * jsonb type recv function * * The type is sent as text in binary mode, so this is almost the same * as the input function, but it's prefixed with a version number so we * can change the binary format sent in future if necessary. For now, * only version 1 is supported. */ Datum jsonb_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); int version = pq_getmsgint(buf, 1); char *str; int nbytes; if (version == 1) str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); else elog(ERROR, "Unsupported jsonb version number %d", version); return jsonb_from_cstring(str, nbytes); }
void deserialize_filesystem_credentials(char *binary, int len, HTAB **currentFilesystemCredentials, MemoryContext *currentFilesystemCredentialsMemoryContext) { bool found = false; struct FileSystemCredentialKey key; struct FileSystemCredential *entry; Insist(NULL != currentFilesystemCredentials); Insist(NULL != currentFilesystemCredentialsMemoryContext); Insist(NULL != binary && Gp_role == GP_ROLE_EXECUTE && len > 0); create_filesystem_credentials_internal(currentFilesystemCredentials, currentFilesystemCredentialsMemoryContext); MemoryContext old = MemoryContextSwitchTo(*currentFilesystemCredentialsMemoryContext); StringInfoData buffer; initStringInfoOfString(&buffer, binary, len); while (buffer.cursor < buffer.len) { memset(&key, 0, sizeof(key)); StrNCpy(key.host, pq_getmsgstring(&buffer), sizeof(key.host)); StrNCpy(key.protocol, pq_getmsgstring(&buffer), sizeof(key.protocol)); key.port = pq_getmsgint(&buffer, sizeof(int)); entry = (struct FileSystemCredential *) hash_search( *currentFilesystemCredentials, &key, HASH_ENTER, &found); if (found) elog(ERROR, "dispatched duplicate file system credential"); entry->credential = pstrdup(pq_getmsgstring(&buffer)); } if (buffer.cursor != buffer.len) elog(ERROR, "dispatched invalid file system credential"); MemoryContextSwitchTo(old); }
/* * Read INSERT from stream. * * Fills the new tuple. */ LogicalRepRelId logicalrep_read_insert(StringInfo in, LogicalRepTupleData *newtup) { char action; LogicalRepRelId relid; /* read the relation id */ relid = pq_getmsgint(in, 4); action = pq_getmsgbyte(in); if (action != 'N') elog(ERROR, "expected new tuple but got %d", action); logicalrep_read_tuple(in, newtup); return relid; }
/* * Read DELETE from stream. * * Fills the old tuple. */ LogicalRepRelId logicalrep_read_delete(StringInfo in, LogicalRepTupleData *oldtup) { char action; LogicalRepRelId relid; /* read the relation id */ relid = pq_getmsgint(in, 4); /* read and verify action */ action = pq_getmsgbyte(in); if (action != 'K' && action != 'O') elog(ERROR, "expected action 'O' or 'K', got %c", action); logicalrep_read_tuple(in, oldtup); return relid; }
/* * Read the relation info from stream and return as LogicalRepRelation. */ LogicalRepRelation * logicalrep_read_rel(StringInfo in) { LogicalRepRelation *rel = palloc(sizeof(LogicalRepRelation)); rel->remoteid = pq_getmsgint(in, 4); /* Read relation name from stream */ rel->nspname = pstrdup(logicalrep_read_namespace(in)); rel->relname = pstrdup(pq_getmsgstring(in)); /* Read the replica identity. */ rel->replident = pq_getmsgbyte(in); /* Get attribute description */ logicalrep_read_attrs(in, rel); return rel; }
Datum ipaddr_recv(PG_FUNCTION_ARGS) { StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); IP ip; int af, bits, flag, nbytes; /* we copy the external format used by inet/cidr, just because. */ af = pq_getmsgbyte(buf); if (af != PGSQL_AF_INET && af != PGSQL_AF_INET6) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid address family in external IP value"))); bits = pq_getmsgbyte(buf); if (bits != ip_maxbits(af)) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid bit length in external IP value"))); flag = pq_getmsgbyte(buf); /* ignored */ nbytes = pq_getmsgbyte(buf); if (nbytes*8 != bits) ereport(ERROR, (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), errmsg("invalid address length in external IP value"))); switch (af) { case PGSQL_AF_INET: ip.ip4 = (IP4) pq_getmsgint(buf, sizeof(IP4)); break; case PGSQL_AF_INET6: ip.ip6.bits[0] = pq_getmsgint64(buf); ip.ip6.bits[1] = pq_getmsgint64(buf); break; } PG_RETURN_IP_P(ip_pack(af, &ip)); }
/* * Read UPDATE from stream. */ LogicalRepRelId logicalrep_read_update(StringInfo in, bool *has_oldtuple, LogicalRepTupleData *oldtup, LogicalRepTupleData *newtup) { char action; LogicalRepRelId relid; /* read the relation id */ relid = pq_getmsgint(in, 4); /* read and verify action */ action = pq_getmsgbyte(in); if (action != 'K' && action != 'O' && action != 'N') elog(ERROR, "expected action 'N', 'O' or 'K', got %c", action); /* check for old tuple */ if (action == 'K' || action == 'O') { logicalrep_read_tuple(in, oldtup); *has_oldtuple = true; action = pq_getmsgbyte(in); } else *has_oldtuple = false; /* check for new tuple */ if (action != 'N') elog(ERROR, "expected action 'N', got %c", action); logicalrep_read_tuple(in, newtup); return relid; }