static bool gbt_datelt(const void *a, const void *b) { return DatumGetBool( DirectFunctionCall2(date_lt, DateADTGetDatum(*((DateADT *) a)), DateADTGetDatum(*((DateADT *) b))) ); }
static float8 gdb_date_dist(const void *a, const void *b) { /* we assume the difference can't overflow */ Datum diff = DirectFunctionCall2(date_mi, DateADTGetDatum(*((const DateADT *) a)), DateADTGetDatum(*((const DateADT *) b))); return (float8) Abs(DatumGetInt32(diff)); }
static int gbt_datekey_cmp(const void *a, const void *b) { dateKEY *ia = (dateKEY *) (((Nsrt *) a)->t); dateKEY *ib = (dateKEY *) (((Nsrt *) b)->t); int res; res = DatumGetInt32(DirectFunctionCall2(date_cmp, DateADTGetDatum(ia->lower), DateADTGetDatum(ib->lower))); if (res == 0) return DatumGetInt32(DirectFunctionCall2(date_cmp, DateADTGetDatum(ia->upper), DateADTGetDatum(ib->upper))); return res; }
Datum HASHAPI_Hash_1_date(PG_FUNCTION_ARGS) { int32 num_segs; /* number of segments */ DateADT val1; /* date value */ unsigned int targetbucket; /* 0-based */ int16 algorithm; /* hashing algorithm */ Datum d1; Oid oid; /* Get number of segments */ num_segs = PG_GETARG_INT32(0); /* Get hashing algoriithm */ algorithm = PG_GETARG_INT16(1); /* Get the value to hash */ val1 = PG_GETARG_DATEADT(2); d1 = DateADTGetDatum(val1); /* create a CdbHash for this hash test. */ h = makeCdbHash(num_segs, algorithm); /* init cdb hash */ cdbhashinit(h); oid = DATEOID; cdbhash(h, d1, oid); /* reduce the result hash value */ targetbucket = cdbhashreduce(h); PG_RETURN_INT32(targetbucket); /* return target bucket (segID) */ }
/* * Convert a compressed leaf item back to the original type, for index-only * scans. */ GISTENTRY * gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo) { GISTENTRY *retval; Datum datum; Assert(tinfo->indexsize >= 2 * tinfo->size); /* * Get the original Datum from the stored datum. On leaf entries, the * lower and upper bound are the same. We just grab the lower bound and * return it. */ switch (tinfo->t) { case gbt_t_int2: datum = Int16GetDatum(*(int16 *) entry->key); break; case gbt_t_int4: datum = Int32GetDatum(*(int32 *) entry->key); break; case gbt_t_int8: datum = Int64GetDatum(*(int64 *) entry->key); break; case gbt_t_oid: case gbt_t_enum: datum = ObjectIdGetDatum(*(Oid *) entry->key); break; case gbt_t_float4: datum = Float4GetDatum(*(float4 *) entry->key); break; case gbt_t_float8: datum = Float8GetDatum(*(float8 *) entry->key); break; case gbt_t_date: datum = DateADTGetDatum(*(DateADT *) entry->key); break; case gbt_t_time: datum = TimeADTGetDatum(*(TimeADT *) entry->key); break; case gbt_t_ts: datum = TimestampGetDatum(*(Timestamp *) entry->key); break; case gbt_t_cash: datum = CashGetDatum(*(Cash *) entry->key); break; default: datum = PointerGetDatum(entry->key); } retval = palloc(sizeof(GISTENTRY)); gistentryinit(*retval, datum, entry->rel, entry->page, entry->offset, false); return retval; }
Datum gbt_date_penalty(PG_FUNCTION_ARGS) { dateKEY *origentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key); dateKEY *newentry = (dateKEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key); float *result = (float *) PG_GETARG_POINTER(2); int32 diff, res; diff = DatumGetInt32(DirectFunctionCall2( date_mi, DateADTGetDatum(newentry->upper), DateADTGetDatum(origentry->upper))); res = Max(diff, 0); diff = DatumGetInt32(DirectFunctionCall2( date_mi, DateADTGetDatum(origentry->lower), DateADTGetDatum(newentry->lower))); res += Max(diff, 0); *result = 0.0; if (res > 0) { diff = DatumGetInt32(DirectFunctionCall2( date_mi, DateADTGetDatum(origentry->upper), DateADTGetDatum(origentry->lower))); *result += FLT_MIN; *result += (float) (res / ((double) (res + diff))); *result *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); } PG_RETURN_POINTER(result); }
/* * 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; }
static Datum leftmostvalue_date(void) { return DateADTGetDatum(DATEVAL_NOBEGIN); }
static Datum dbms_pipe_unpack_message(PG_FUNCTION_ARGS, message_data_type dtype) { Oid tupType; void *ptr; message_data_type type; int32 size; Datum result; message_data_type next_type; if (input_buffer == NULL || input_buffer->items_count <= 0 || input_buffer->next == NULL || input_buffer->next->type == IT_NO_MORE_ITEMS) PG_RETURN_NULL(); next_type = input_buffer->next->type; if (next_type != dtype) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("datatype mismatch"), errdetail("unpack unexpected type: %d", next_type))); ptr = unpack_field(input_buffer, &type, &size, &tupType); Assert(ptr != NULL); switch (type) { case IT_TIMESTAMPTZ: result = TimestampTzGetDatum(*(TimestampTz*)ptr); break; case IT_DATE: result = DateADTGetDatum(*(DateADT*)ptr); break; case IT_VARCHAR: case IT_NUMBER: case IT_BYTEA: result = PointerGetDatum(cstring_to_text_with_len(ptr, size)); break; case IT_RECORD: { #if PG_VERSION_NUM >= 120000 LOCAL_FCINFO(info, 3); #else FunctionCallInfoData info_data; FunctionCallInfo info = &info_data; #endif StringInfoData buf; text *data = cstring_to_text_with_len(ptr, size); buf.data = VARDATA(data); buf.len = VARSIZE(data) - VARHDRSZ; buf.maxlen = buf.len; buf.cursor = 0; /* * Normally one would call record_recv() using DirectFunctionCall3, * but that does not work since record_recv wants to cache some data * using fcinfo->flinfo->fn_extra. So we need to pass it our own * flinfo parameter. */ InitFunctionCallInfoData(*info, fcinfo->flinfo, 3, InvalidOid, NULL, NULL); init_args_3(info, PointerGetDatum(&buf), ObjectIdGetDatum(tupType), Int32GetDatum(-1)); result = record_recv(info); break; } default: elog(ERROR, "unexpected type: %d", type); result = (Datum) 0; /* keep compiler quiet */ } if (input_buffer->items_count == 0) { pfree(input_buffer); input_buffer = NULL; } PG_RETURN_DATUM(result); }