Datum float4_accum(PG_FUNCTION_ARGS) { ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); float4 newval4 = PG_GETARG_FLOAT4(1); float8 *transvalues; float8 N, sumX, sumX2, newval; Datum transdatums[3]; ArrayType *result; transvalues = check_float8_array(transarray, "float4_accum"); N = transvalues[0]; sumX = transvalues[1]; sumX2 = transvalues[2]; /* Do arithmetic in float8 for best accuracy */ newval = newval4; N += 1.0; sumX += newval; sumX2 += newval * newval; transdatums[0] = Float8GetDatumFast(N); transdatums[1] = Float8GetDatumFast(sumX); transdatums[2] = Float8GetDatumFast(sumX2); result = construct_array(transdatums, 3, FLOAT8OID, sizeof(float8), false /* float8 byval */ , 'd'); PG_RETURN_ARRAYTYPE_P(result); }
Datum spherepoint_xyz(PG_FUNCTION_ARGS) { SPoint * p = ( SPoint * ) PG_GETARG_POINTER ( 0 ) ; Datum dret[3]; ArrayType *result; static Vector3D v ; spoint_vector3d ( &v , p ); dret[0] = Float8GetDatumFast(v.x); dret[1] = Float8GetDatumFast(v.y); dret[2] = Float8GetDatumFast(v.z); result = construct_array ( dret , 3, FLOAT8OID, sizeof(float8), false /* float8 byval */ , 'd' ); PG_RETURN_ARRAYTYPE_P(result); }
/* * Hash function for float8[] */ static int float8arr_hash_internal(ArrayType *array) { SparseData sdata = sdata_uncompressed_from_float8arr_internal(array); double l1norm = l1norm_sdata_values_double(sdata); int arr_hash = DirectFunctionCall1(hashfloat8, Float8GetDatumFast(l1norm)); pfree(sdata); return(arr_hash); }
Datum spherepoint_xyz(PG_FUNCTION_ARGS) { SPoint *p = (SPoint *) PG_GETARG_POINTER(0); Datum dret[3]; ArrayType *result; Vector3D v; spoint_vector3d(&v, p); dret[0] = Float8GetDatumFast(v.x); dret[1] = Float8GetDatumFast(v.y); dret[2] = Float8GetDatumFast(v.z); #ifdef USE_FLOAT8_BYVAL result = construct_array(dret, 3, FLOAT8OID, sizeof(float8), true, 'd'); #else result = construct_array(dret, 3, FLOAT8OID, sizeof(float8), false, 'd'); #endif PG_RETURN_ARRAYTYPE_P(result); }
/* * variance and stddev - mathmatical compatible result can be lead using * nrows, psum(X) and psum(X*X). So, we track these variables. */ Datum pgstrom_variance_float8_accum(PG_FUNCTION_ARGS) { ArrayType *transarray = PG_GETARG_ARRAYTYPE_P(0); int32 nrows = PG_GETARG_INT32(1); float8 psumX = PG_GETARG_FLOAT8(2); float8 psumX2 = PG_GETARG_FLOAT8(3); float8 *transvalues; float8 newN; float8 newSumX; float8 newSumX2; transvalues = check_float8_array(transarray, 3); newN = transvalues[0] + (float8) nrows; newSumX = transvalues[1] + psumX; check_float8_valid(newSumX, isinf(transvalues[1]) || isinf(psumX), true); newSumX2 = transvalues[2] + psumX2; check_float8_valid(newSumX2, isinf(transvalues[2]) || isinf(psumX2), true); if (AggCheckCallContext(fcinfo, NULL)) { transvalues[0] = newN; transvalues[1] = newSumX; transvalues[2] = newSumX2; PG_RETURN_ARRAYTYPE_P(transarray); } else { Datum transdatums[3]; ArrayType *result; transdatums[0] = Float8GetDatumFast(newN); transdatums[1] = Float8GetDatumFast(newSumX); transdatums[2] = Float8GetDatumFast(newSumX2); result = construct_array(transdatums, 3, FLOAT8OID, sizeof(float8), FLOAT8PASSBYVAL, 'd'); PG_RETURN_ARRAYTYPE_P(result); } }
Datum months_between(PG_FUNCTION_ARGS) { DateADT date1 = PG_GETARG_DATEADT(0); DateADT date2 = PG_GETARG_DATEADT(1); int y1, m1, d1; int y2, m2, d2; float8 result; j2date(date1 + POSTGRES_EPOCH_JDATE, &y1, &m1, &d1); j2date(date2 + POSTGRES_EPOCH_JDATE, &y2, &m2, &d2); /* Ignore day components for last days, or based on a 31-day month. */ if (d1 == days_of_month(y1, m1) && d2 == days_of_month(y2, m2)) result = (y1 - y2) * 12 + (m1 - m2); else result = (y1 - y2) * 12 + (m1 - m2) + (d1 - d2) / 31.0; PG_RETURN_NUMERIC( DirectFunctionCall1(float8_numeric, Float8GetDatumFast(result))); }
/* * Retrieve statement statistics. */ Datum pg_stat_statements(PG_FUNCTION_ARGS) { ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; TupleDesc tupdesc; Tuplestorestate *tupstore; MemoryContext per_query_ctx; MemoryContext oldcontext; Oid userid = GetUserId(); bool is_superuser = superuser(); HASH_SEQ_STATUS hash_seq; pgssEntry *entry; if (!pgss || !pgss_hash) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("pg_stat_statements must be loaded via shared_preload_libraries"))); /* check to see if caller supports us returning a tuplestore */ if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("set-valued function called in context that cannot accept a set"))); if (!(rsinfo->allowedModes & SFRM_Materialize)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("materialize mode required, but it is not " \ "allowed in this context"))); /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; oldcontext = MemoryContextSwitchTo(per_query_ctx); tupstore = tuplestore_begin_heap(true, false, work_mem); rsinfo->returnMode = SFRM_Materialize; rsinfo->setResult = tupstore; rsinfo->setDesc = tupdesc; MemoryContextSwitchTo(oldcontext); LWLockAcquire(pgss->lock, LW_SHARED); hash_seq_init(&hash_seq, pgss_hash); while ((entry = hash_seq_search(&hash_seq)) != NULL) { Datum values[PG_STAT_STATEMENTS_COLS]; bool nulls[PG_STAT_STATEMENTS_COLS]; int i = 0; Counters tmp; memset(values, 0, sizeof(values)); memset(nulls, 0, sizeof(nulls)); values[i++] = ObjectIdGetDatum(entry->key.userid); values[i++] = ObjectIdGetDatum(entry->key.dbid); if (is_superuser || entry->key.userid == userid) { char *qstr; qstr = (char *) pg_do_encoding_conversion((unsigned char *) entry->query, entry->key.query_len, entry->key.encoding, GetDatabaseEncoding()); values[i++] = CStringGetTextDatum(qstr); if (qstr != entry->query) pfree(qstr); } else values[i++] = CStringGetTextDatum("<insufficient privilege>"); /* copy counters to a local variable to keep locking time short */ { volatile pgssEntry *e = (volatile pgssEntry *) entry; SpinLockAcquire(&e->mutex); tmp = e->counters; SpinLockRelease(&e->mutex); } values[i++] = Int64GetDatumFast(tmp.calls); values[i++] = Float8GetDatumFast(tmp.total_time); values[i++] = Int64GetDatumFast(tmp.rows); values[i++] = Int64GetDatumFast(tmp.shared_blks_hit); values[i++] = Int64GetDatumFast(tmp.shared_blks_read); values[i++] = Int64GetDatumFast(tmp.shared_blks_written); values[i++] = Int64GetDatumFast(tmp.local_blks_hit); values[i++] = Int64GetDatumFast(tmp.local_blks_read); values[i++] = Int64GetDatumFast(tmp.local_blks_written); values[i++] = Int64GetDatumFast(tmp.temp_blks_read); values[i++] = Int64GetDatumFast(tmp.temp_blks_written); Assert(i == PG_STAT_STATEMENTS_COLS); tuplestore_putvalues(tupstore, tupdesc, values, nulls); } LWLockRelease(pgss->lock); /* clean up and return the tuplestore */ tuplestore_donestoring(tupstore); return (Datum) 0; }
/** * @brief Entry point of the user-defined function for pg_bulkload. * @return Returns number of loaded tuples. If the case of errors, -1 will be * returned. */ Datum pg_bulkload(PG_FUNCTION_ARGS) { Reader *rd = NULL; Writer *wt = NULL; Datum options; MemoryContext ctx; MemoryContext ccxt; PGRUsage ru0; PGRUsage ru1; int64 count; int64 parse_errors; int64 skip; WriterResult ret; char *start; char *end; float8 system; float8 user; float8 duration; TupleDesc tupdesc; Datum values[PG_BULKLOAD_COLS]; bool nulls[PG_BULKLOAD_COLS]; HeapTuple result; /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); BULKLOAD_PROFILE_PUSH(); pg_rusage_init(&ru0); /* must be the super user */ if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("must be superuser to use pg_bulkload"))); options = PG_GETARG_DATUM(0); ccxt = CurrentMemoryContext; /* * STEP 1: Initialization */ /* parse options and create reader and writer */ ParseOptions(options, &rd, &wt, ru0.tv.tv_sec); /* initialize reader */ ReaderInit(rd); /* * We need to split PG_TRY block because gcc optimizes if-branches with * longjmp codes too much. Local variables initialized in either branch * cannot be handled another branch. */ PG_TRY(); { /* truncate heap */ if (wt->truncate) TruncateTable(wt->relid); /* initialize writer */ WriterInit(wt); /* initialize checker */ CheckerInit(&rd->checker, wt->rel, wt->tchecker); /* initialize parser */ ParserInit(rd->parser, &rd->checker, rd->infile, wt->desc, wt->multi_process, PG_GET_COLLATION()); } PG_CATCH(); { if (rd) ReaderClose(rd, true); if (wt) WriterClose(wt, true); PG_RE_THROW(); } PG_END_TRY(); /* No throwable codes here! */ PG_TRY(); { /* create logger */ CreateLogger(rd->logfile, wt->verbose, rd->infile[0] == ':'); start = timeval_to_cstring(ru0.tv); LoggerLog(INFO, "\npg_bulkload %s on %s\n\n", PG_BULKLOAD_VERSION, start); ReaderDumpParams(rd); WriterDumpParams(wt); LoggerLog(INFO, "\n"); BULKLOAD_PROFILE(&prof_init); /* * STEP 2: Build heap */ /* Switch into its memory context */ Assert(wt->context); ctx = MemoryContextSwitchTo(wt->context); /* Loop for each input file record. */ while (wt->count < rd->limit) { HeapTuple tuple; CHECK_FOR_INTERRUPTS(); /* read tuple */ BULKLOAD_PROFILE_PUSH(); tuple = ReaderNext(rd); BULKLOAD_PROFILE_POP(); BULKLOAD_PROFILE(&prof_reader); if (tuple == NULL) break; /* write tuple */ BULKLOAD_PROFILE_PUSH(); WriterInsert(wt, tuple); wt->count += 1; BULKLOAD_PROFILE_POP(); BULKLOAD_PROFILE(&prof_writer); MemoryContextReset(wt->context); BULKLOAD_PROFILE(&prof_reset); } MemoryContextSwitchTo(ctx); /* * STEP 3: Finalize heap and merge indexes */ count = wt->count; parse_errors = rd->parse_errors; /* * close writer first and reader second because shmem_exit callback * is managed by a simple stack. */ ret = WriterClose(wt, false); wt = NULL; skip = ReaderClose(rd, false); rd = NULL; } PG_CATCH(); { ErrorData *errdata; MemoryContext ecxt; ecxt = MemoryContextSwitchTo(ccxt); errdata = CopyErrorData(); LoggerLog(INFO, "%s\n", errdata->message); FreeErrorData(errdata); /* close writer first, and reader second */ if (wt) WriterClose(wt, true); if (rd) ReaderClose(rd, true); MemoryContextSwitchTo(ecxt); PG_RE_THROW(); } PG_END_TRY(); count -= ret.num_dup_new; LoggerLog(INFO, "\n" " " int64_FMT " Rows skipped.\n" " " int64_FMT " Rows successfully loaded.\n" " " int64_FMT " Rows not loaded due to parse errors.\n" " " int64_FMT " Rows not loaded due to duplicate errors.\n" " " int64_FMT " Rows replaced with new rows.\n\n", skip, count, parse_errors, ret.num_dup_new, ret.num_dup_old); pg_rusage_init(&ru1); system = diffTime(ru1.ru.ru_stime, ru0.ru.ru_stime); user = diffTime(ru1.ru.ru_utime, ru0.ru.ru_utime); duration = diffTime(ru1.tv, ru0.tv); end = timeval_to_cstring(ru1.tv); memset(nulls, 0, sizeof(nulls)); values[0] = Int64GetDatum(skip); values[1] = Int64GetDatum(count); values[2] = Int64GetDatum(parse_errors); values[3] = Int64GetDatum(ret.num_dup_new); values[4] = Int64GetDatum(ret.num_dup_old); values[5] = Float8GetDatumFast(system); values[6] = Float8GetDatumFast(user); values[7] = Float8GetDatumFast(duration); LoggerLog(INFO, "Run began on %s\n" "Run ended on %s\n\n" "CPU %.2fs/%.2fu sec elapsed %.2f sec\n", start, end, system, user, duration); LoggerClose(); result = heap_form_tuple(tupdesc, values, nulls); BULKLOAD_PROFILE(&prof_fini); BULKLOAD_PROFILE_POP(); BULKLOAD_PROFILE_PRINT(); PG_RETURN_DATUM(HeapTupleGetDatum(result)); }