char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber) { Datum origval, val, result; bool isnull; Oid typoid, foutoid, typioparam; int32 typmod; bool typisvarlena; SPI_result = 0; if (fnumber > tuple->t_data->t_natts || fnumber == 0 || fnumber <= FirstLowInvalidHeapAttributeNumber) { SPI_result = SPI_ERROR_NOATTRIBUTE; return NULL; } origval = heap_getattr(tuple, fnumber, tupdesc, &isnull); if (isnull) return NULL; if (fnumber > 0) { typoid = tupdesc->attrs[fnumber - 1]->atttypid; typmod = tupdesc->attrs[fnumber - 1]->atttypmod; } else { typoid = (SystemAttributeDefinition(fnumber, true))->atttypid; typmod = -1; } getTypeOutputInfo(typoid, &foutoid, &typioparam, &typisvarlena); /* * If we have a toasted datum, forcibly detoast it here to avoid * memory leakage inside the type's output routine. */ if (typisvarlena) val = PointerGetDatum(PG_DETOAST_DATUM(origval)); else val = origval; result = OidFunctionCall3(foutoid, val, ObjectIdGetDatum(typioparam), Int32GetDatum(typmod)); /* Clean up detoasted copy, if any */ if (val != origval) pfree(DatumGetPointer(val)); return DatumGetCString(result); }
/* ---------------- * index_beginscan - start a scan of an index * * Note: heapRelation may be NULL if there is no intention of calling * index_getnext on this scan; index_getnext_indexitem will not use the * heapRelation link (nor the snapshot). However, the caller had better * be holding some kind of lock on the heap relation in any case, to ensure * no one deletes it (or the index) out from under us. * ---------------- */ IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key) { IndexScanDesc scan; RegProcedure procedure; RELATION_CHECKS; GET_REL_PROCEDURE(beginscan, ambeginscan); RelationIncrementReferenceCount(indexRelation); /* * Acquire AccessShareLock for the duration of the scan * * Note: we could get an SI inval message here and consequently have to * rebuild the relcache entry. The refcount increment above ensures * that we will rebuild it and not just flush it... */ LockRelation(indexRelation, AccessShareLock); /* * Tell the AM to open a scan. */ scan = (IndexScanDesc) DatumGetPointer(OidFunctionCall3(procedure, PointerGetDatum(indexRelation), Int32GetDatum(nkeys), PointerGetDatum(key))); /* * Save additional parameters into the scandesc. Everything else was * set up by RelationGetIndexScan. */ scan->heapRelation = heapRelation; scan->xs_snapshot = snapshot; /* * We want to look up the amgettuple procedure just once per scan, not * once per index_getnext call. So do it here and save the fmgr info * result in the scan descriptor. */ GET_SCAN_PROCEDURE(beginscan, amgettuple); fmgr_info(procedure, &scan->fn_getnext); return scan; }
/* ---------------- * index_bulk_delete - do mass deletion of index entries * * callback routine tells whether a given main-heap tuple is * to be deleted * * return value is an optional palloc'd struct of statistics * ---------------- */ IndexBulkDeleteResult * index_bulk_delete(Relation indexRelation, IndexBulkDeleteCallback callback, void *callback_state) { RegProcedure procedure; IndexBulkDeleteResult *result; RELATION_CHECKS; GET_REL_PROCEDURE(bulk_delete, ambulkdelete); result = (IndexBulkDeleteResult *) DatumGetPointer(OidFunctionCall3(procedure, PointerGetDatum(indexRelation), PointerGetDatum((Pointer) callback), PointerGetDatum(callback_state))); return result; }
/* * Convert the Datum "input" that is of type "typeoid" to a C string. */ static char * type_to_cstring(Datum input, Oid typeoid) { HeapTuple typetuple; Form_pg_type pg_type_entry; Datum ret; typetuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(typeoid), 0, 0, 0); if (!HeapTupleIsValid(typetuple)) elog(ERROR, "cache lookup failed for type %u", typeoid); pg_type_entry = (Form_pg_type) GETSTRUCT(typetuple); ret = OidFunctionCall3(pg_type_entry->typoutput, input, 0, -1); ReleaseSysCache(typetuple); return DatumGetCString(ret); }
/* * Convert the C string "input" to a Datum of type "typeoid". */ static Datum cstring_to_type(char * input, Oid typeoid) { HeapTuple typetuple; Form_pg_type pg_type_entry; Datum ret; typetuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(typeoid), 0, 0, 0); if (!HeapTupleIsValid(typetuple)) elog(ERROR, "cache lookup failed for type %u", typeoid); pg_type_entry = (Form_pg_type) GETSTRUCT(typetuple); ret = OidFunctionCall3(pg_type_entry->typinput, CStringGetDatum(input), 0, -1); ReleaseSysCache(typetuple); PG_RETURN_DATUM(ret); }
/* ---------------- * index_vacuum_cleanup - do post-deletion cleanup of an index * * return value is an optional palloc'd struct of statistics * ---------------- */ IndexBulkDeleteResult * index_vacuum_cleanup(Relation indexRelation, IndexVacuumCleanupInfo *info, IndexBulkDeleteResult *stats) { RegProcedure procedure; IndexBulkDeleteResult *result; RELATION_CHECKS; /* It's okay for an index AM not to have a vacuumcleanup procedure */ if (!RegProcedureIsValid(indexRelation->rd_am->amvacuumcleanup)) return stats; GET_REL_PROCEDURE(vacuum_cleanup, amvacuumcleanup); result = (IndexBulkDeleteResult *) DatumGetPointer(OidFunctionCall3(procedure, PointerGetDatum(indexRelation), PointerGetDatum((Pointer) info), PointerGetDatum((Pointer) stats))); return result; }
/* * index_build - invoke access-method-specific index build procedure */ void index_build(Relation heapRelation, Relation indexRelation, IndexInfo *indexInfo) { RegProcedure procedure; /* * sanity checks */ Assert(RelationIsValid(indexRelation)); Assert(PointerIsValid(indexRelation->rd_am)); procedure = indexRelation->rd_am->ambuild; Assert(RegProcedureIsValid(procedure)); /* * Call the access method's build procedure */ OidFunctionCall3(procedure, PointerGetDatum(heapRelation), PointerGetDatum(indexRelation), PointerGetDatum(indexInfo)); }
SvecType * svec_in_internal(char * str) { char *values; ArrayType *pgarray_vals,*pgarray_ix; double *vals, *vals_temp; StringInfo index; int64 *u_index; int32_t num_values,total_value_count; SparseData sdata; SvecType *result; bits8 *bitmap; int bitmask; int i,j; /* Read in the two arrays defining the Sparse Vector, first is the array * of run lengths (the count array), the second is an array of the * unique values (the data array). * * The input format is a pair of standard Postgres arrays separated by * a colon, like this: * {1,10,1,5,1}:{4.3,0,0.2,0,7.4} * * For now, the data array must only have float8 elements. */ if ((values=strchr(str,':')) == NULL) { ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Invalid input string for svec"))); } else { *values = '\0'; values = values+1; } /* Get the count and data arrays */ pgarray_ix = DatumGetArrayTypeP( OidFunctionCall3(F_ARRAY_IN,CStringGetDatum(str), ObjectIdGetDatum(INT8OID),Int32GetDatum(-1))); pgarray_vals = DatumGetArrayTypeP( OidFunctionCall3(F_ARRAY_IN,CStringGetDatum(values), ObjectIdGetDatum(FLOAT8OID),Int32GetDatum(-1))); num_values = *(ARR_DIMS(pgarray_ix)); u_index = (int64 *)ARR_DATA_PTR(pgarray_ix); vals = (double *)ARR_DATA_PTR(pgarray_vals); /* The count and value arrays must be non-empty */ int size1 = ARR_NDIM(pgarray_ix); int size2 = ARR_NDIM(pgarray_vals); if (size1 == 0 || size2 == 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("The count and value arrays must be non-empty"))); /* The count and value arrays must have the same dimension */ if (num_values != *(ARR_DIMS(pgarray_vals))) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Unique value count not equal to run length count %d != %d", num_values, *(ARR_DIMS(pgarray_vals))))); /* Count array cannot have NULLs */ if (ARR_HASNULL(pgarray_ix)) ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), errmsg("NULL value in the count array."))); /* If the data array has NULLs, then we need to create an array to * store the NULL values as NVP values defined in float_specials.h. */ if (ARR_HASNULL(pgarray_vals)) { vals_temp = vals; vals = (double *)palloc(sizeof(float8) * num_values); bitmap = ARR_NULLBITMAP(pgarray_vals); bitmask = 1; j = 0; for (i=0; i<num_values; i++) { if (bitmap && (*bitmap & bitmask) == 0) // if NULL vals[i] = NVP; else { vals[i] = vals_temp[j]; j++; } if (bitmap) { // advance bitmap pointer bitmask <<= 1; if (bitmask == 0x100) { bitmap++; bitmask = 1; } } } } /* Make an empty StringInfo because we have the data array already */ index = makeStringInfo(); total_value_count = 0; for (int i=0;i<num_values;i++) { if (u_index[i] <= 0) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Non-positive run length in input"))); total_value_count+=u_index[i]; append_to_rle_index(index,u_index[i]); } sdata = makeInplaceSparseData((char *)vals,index->data, num_values*sizeof(double),index->len,FLOAT8OID, num_values,total_value_count); sdata->type_of_data = FLOAT8OID; result = svec_from_sparsedata(sdata,true); if (total_value_count == 1) result->dimension = -1; //Scalar if (ARR_HASNULL(pgarray_vals)) pfree(vals); pfree(str); /* str is allocated from a strdup */ pfree(pgarray_ix); pfree(pgarray_vals); return result; }
Datum hdfs_get_value(hdfs_opt *opt, Oid pgtyp, int pgtypmod, HiveResultSet *rs, int idx, bool *is_null, int len, int col_type) { Datum value_datum = 0; Datum valueDatum = 0; regproc typeinput; HeapTuple tuple; int typemod; char *value; /* get the type's output function */ tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(pgtyp)); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for type %u", pgtyp); typeinput = ((Form_pg_type)GETSTRUCT(tuple))->typinput; typemod = ((Form_pg_type)GETSTRUCT(tuple))->typtypmod; ReleaseSysCache(tuple); switch (pgtyp) { case BITOID: case BOOLOID: case INT2OID: case INT4OID: case INT8OID: case BYTEAOID: case DATEOID: case TIMEOID: case TIMESTAMPOID: case TIMESTAMPTZOID: case FLOAT4OID: case FLOAT8OID: { char *value; value = hdfs_get_field_as_cstring(opt, rs, idx, is_null, len); /* libhive return an empty string for null value */ if (strlen(value) == 0) { *is_null = true; } else { valueDatum = CStringGetDatum((char*)value); value_datum = OidFunctionCall3(typeinput, valueDatum, ObjectIdGetDatum(pgtyp), Int32GetDatum(typemod)); } } break; case CHAROID: case NAMEOID: case TEXTOID: case BPCHAROID: case VARCHAROID: { switch (col_type) { case HDFS_TINYINT: { char str[10]; value = hdfs_get_field_as_cstring(opt, rs, idx, is_null, len); if (strlen(value) == 0) { *is_null = true; } else { sprintf(str, "%d", value[0]); valueDatum = CStringGetDatum((char*)str); value_datum = OidFunctionCall3(typeinput, valueDatum, ObjectIdGetDatum(pgtyp), Int32GetDatum(typemod)); } } break; default: { value = hdfs_get_field_as_cstring(opt, rs, idx, is_null, len); valueDatum = CStringGetDatum((char*)value); value_datum = OidFunctionCall3(typeinput, valueDatum, ObjectIdGetDatum(pgtyp), Int32GetDatum(typemod)); } break; } } break; default: ereport(ERROR, (errcode(ERRCODE_FDW_INVALID_DATA_TYPE), errmsg("unknown or unsupported PostgreSQL data type"), errhint("Supported data types are BOOL, INT, DATE, TIME, FLOAT, CHAR, TEXT and VARCHAR : %u", pgtyp))); break; } return value_datum; }