Datum linterp_DateADT(PG_FUNCTION_ARGS) { DateADT y0; DateADT y1; int32 dy; float8 p; DateADT result; bool eq_bounds = false; bool eq_abscissas = false; /* Common */ p = linterp_abscissa(fcinfo, &eq_bounds, &eq_abscissas); /* Ordinate type specific code*/ y0 = PG_GETARG_DATEADT(2); y1 = PG_GETARG_DATEADT(4); dy = date_diff(y1, y0); if ( eq_bounds ) { if ( eq_abscissas && dy == 0 ) result = y0; else PG_RETURN_NULL(); } else { result = date_pl_days(y0, (int32) (p * (float8) dy)); } PG_RETURN_DATEADT(result); }
Datum plvdate_bizdays_between (PG_FUNCTION_ARGS) { DateADT day1 = PG_GETARG_DATEADT(0); DateADT day2 = PG_GETARG_DATEADT(1); PG_RETURN_INT32(ora_diff_bizdays(day1,day2)); }
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) */ }
Datum add_months(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int n = PG_GETARG_INT32(1); int y, m, d; int days; DateADT result; div_t v; bool last_day; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); last_day = (d == days_of_month(y, m)); v = div(y * 12 + m - 1 + n, 12); y = v.quot; if (y < 0) y += 1; /* offset because of year 0 */ m = v.rem + 1; days = days_of_month(y, m); if (last_day || d > days) d = days; result = date2j(y, m, d) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT (result); }
Datum plvdate_isbizday (PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int y, m, d; holiday_desc hd; if (0 != ((1 << j2day(day+POSTGRES_EPOCH_JDATE)) & nonbizdays)) return false; if (NULL != bsearch(&day, exceptions, exceptions_c, sizeof(DateADT), dateadt_comp)) return false; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); hd.month = m; hd.day = d; if (use_easter && (m == 3 || m == 4)) { easter_sunday(y, &d, &m); if (m == hd.month && (d == hd.day || d+1 == hd.day)) return false; } PG_RETURN_BOOL (NULL == bsearch(&hd, holidays, holidays_c, sizeof(holiday_desc), holiday_desc_comp)); }
Datum plvdate_prev_bizday (PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); PG_RETURN_DATEADT(ora_add_bizdays(day,-1)); }
Datum plvdate_add_bizdays (PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int days = PG_GETARG_INT32(1); PG_RETURN_DATEADT(ora_add_bizdays(day,days)); }
Datum next_day(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); text *day_txt = PG_GETARG_TEXT_PP(1); const char *str = VARDATA_ANY(day_txt); int len = VARSIZE_ANY_EXHDR(day_txt); int off; int d = -1; #ifdef ENABLE_INTERNATIONALIZED_WEEKDAY /* Check mru_weekdays first for performance. */ if (mru_weekdays) { if ((d = weekday_search(mru_weekdays, str, len)) >= 0) goto found; else mru_weekdays = NULL; } #endif /* * Oracle uses only 3 heading characters of the input. * Ignore all trailing characters. */ if (len >= 3 && (d = ora_seq_prefix_search(str, ora_days, 3)) >= 0) goto found; #ifdef ENABLE_INTERNATIONALIZED_WEEKDAY do { int i; int encoding = GetDatabaseEncoding(); for (i = 0; i < lengthof(WEEKDAYS); i++) { if (encoding == WEEKDAYS[i].encoding) { if ((d = weekday_search(&WEEKDAYS[i], str, len)) >= 0) { mru_weekdays = &WEEKDAYS[i]; goto found; } } } } while(0); #endif CHECK_SEQ_SEARCH(-1, "DAY/Day/day"); found: off = d - j2day(day+POSTGRES_EPOCH_JDATE); PG_RETURN_DATEADT((off <= 0) ? day+off+7 : day + off); }
Datum last_day(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); DateADT result; int y, m, d; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); result = date2j(y, m+1, 1) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(result - 1); }
Datum dbms_pipe_pack_message_date(PG_FUNCTION_ARGS) { DateADT dt = PG_GETARG_DATEADT(0); output_buffer = check_buffer(output_buffer, LOCALMSGSZ); pack_field(output_buffer, IT_DATE, sizeof(dt), &dt, InvalidOid); PG_RETURN_VOID(); }
Datum plvdate_set_nonbizday_day (PG_FUNCTION_ARGS) { DateADT arg1 = PG_GETARG_DATEADT(0); bool arg2 = PG_GETARG_BOOL(1); int y, m, d; holiday_desc hd; if (arg2) { if (holidays_c == MAX_holidays) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("nonbizday registeration error"), errdetail("Too much registered nonbizdays."), errhint("Increase MAX_holidays in 'plvdate.c'."))); j2date(arg1 + POSTGRES_EPOCH_JDATE, &y, &m, &d); hd.month = m; hd.day = d; if (NULL != bsearch(&hd, holidays, holidays_c, sizeof(holiday_desc), holiday_desc_comp)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("nonbizday registeration error"), errdetail("Date is registered."))); holidays[holidays_c].month = m; holidays[holidays_c].day = d; holidays_c += 1; qsort(holidays, holidays_c, sizeof(holiday_desc), holiday_desc_comp); } else { if (exceptions_c == MAX_EXCEPTIONS) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("nonbizday registeration error"), errdetail("Too much registered nonrepeated nonbizdays."), errhint("Increase MAX_EXCEPTIONS in 'plvdate.c'."))); if (NULL != bsearch(&arg1, exceptions, exceptions_c, sizeof(DateADT), dateadt_comp)) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("nonbizday registeration error"), errdetail("Date is registered."))); exceptions[exceptions_c++] = arg1; qsort(exceptions, exceptions_c, sizeof(DateADT), dateadt_comp); } PG_RETURN_VOID(); }
Datum plvdate_isleapyear(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int y, m, d; bool result; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); result = ((( y % 4) == 0) && ((y % 100) != 0)) || ((y / 400) == 0); PG_RETURN_BOOL(result); }
Datum plvdate_days_inmonth(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int result; int y, m, d; j2date(day + POSTGRES_EPOCH_JDATE, &y, &m, &d); result = date2j(y, m+1, 1) - date2j(y, m, 1); PG_RETURN_INT32(result); }
Datum ora_date_round(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); text *fmt = PG_GETARG_TEXT_PP(1); DateADT result; int f = ora_seq_search(VARDATA_ANY(fmt), date_fmt, VARSIZE_ANY_EXHDR(fmt)); CHECK_SEQ_SEARCH(f, "round/trunc format string"); result = _ora_date_round(day, f); PG_RETURN_DATEADT(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))); }
Datum gbt_date_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); DateADT query = PG_GETARG_DATEADT(1); dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key); GBT_NUMKEY_R key; StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); key.lower = (GBT_NUMKEY *) & kkk->lower; key.upper = (GBT_NUMKEY *) & kkk->upper; PG_RETURN_BOOL( gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo) ); }
Datum plvdate_nearest_bizday (PG_FUNCTION_ARGS) { DateADT dt = PG_GETARG_DATEADT(0); DateADT d1, d2, res; d1 = ora_add_bizdays(dt, -1); d2 = ora_add_bizdays(dt, 1); if ((dt - d1) > (d2 - dt)) res = d2; else res = d1; PG_RETURN_DATEADT(res); }
Datum gbt_date_distance(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); DateADT query = PG_GETARG_DATEADT(1); /* Oid subtype = PG_GETARG_OID(3); */ dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key); GBT_NUMKEY_R key; key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; PG_RETURN_FLOAT8( gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo) ); }
Datum plvdate_unset_nonbizday_day (PG_FUNCTION_ARGS) { DateADT arg1 = PG_GETARG_DATEADT(0); bool arg2 = PG_GETARG_BOOL(1); int y, m, d; bool found = false; int i; if (arg2) { j2date(arg1 + POSTGRES_EPOCH_JDATE, &y, &m, &d); for (i = 0; i < holidays_c; i++) { if (!found && holidays[i].month == m && holidays[i].day == d) found = true; else if (found) { holidays[i-1].month = holidays[i].month; holidays[i-1].day = holidays[i].day; } } if (found) holidays_c -= 1; } else { for (i = 0; i < exceptions_c; i++) if (!found && exceptions[i] == arg1) found = true; else if (found) exceptions[i-1] = exceptions[i]; if (found) exceptions_c -= 1; } if (!found) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("nonbizday unregisteration error"), errdetail("Nonbizday not found."))); PG_RETURN_VOID(); }
/* next_day(date, integer) is not documented in Oracle manual, but ... */ Datum next_day_by_index(PG_FUNCTION_ARGS) { DateADT day = PG_GETARG_DATEADT(0); int idx = PG_GETARG_INT32(1); int off; /* * off is 1..7 (Sun..Sat). * * TODO: It should be affected by NLS_TERRITORY. For example, * 1..7 should be interpreted as Mon..Sun in GERMAN. */ CHECK_SEQ_SEARCH((idx < 1 || 7 < idx) ? -1 : 0, "DAY/Day/day"); /* j2day returns 0..6 as Sun..Sat */ off = (idx - 1) - j2day(day+POSTGRES_EPOCH_JDATE); PG_RETURN_DATEADT((off <= 0) ? day+off+7 : day + off); }
Datum gbt_date_consistent(PG_FUNCTION_ARGS) { GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); DateADT query = PG_GETARG_DATEADT(1); StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); /* Oid subtype = PG_GETARG_OID(3); */ bool *recheck = (bool *) PG_GETARG_POINTER(4); dateKEY *kkk = (dateKEY *) DatumGetPointer(entry->key); GBT_NUMKEY_R key; /* All cases served by this function are exact */ *recheck = false; key.lower = (GBT_NUMKEY *) &kkk->lower; key.upper = (GBT_NUMKEY *) &kkk->upper; PG_RETURN_BOOL( gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo) ); }
/* * linterp_abscissa * * Common code that checks arguments. The result is a floating point value * representing what fraction of the distance x lies along the interval from * x0 to x1. It can be negative or greater than one (extrapolation) though * this isn't the intended use. If x0 == x1, then the fraction is not * determined and the function returns 0 and sets *notnull false. In all * other cases (except error exits) *notnull is set to true. An additional * flag indicates whether the abscissa value is equal to the lower boundary * value. */ static float8 linterp_abscissa(PG_FUNCTION_ARGS, bool *p_eq_bounds, bool *p_eq_abscissas) { Oid x_type; Oid x0_type; Oid x1_type; Oid y0_type; Oid y1_type; float8 p = 0; bool eq_bounds = false; bool eq_abscissas = false; /* The abscissa (x) arguments are nominally declared anyelement. * All the type checking is up to us. We insist that the types * are exactly alike. Explicit casts may be needed. */ x_type = get_fn_expr_argtype(fcinfo->flinfo, 0); x0_type = get_fn_expr_argtype(fcinfo->flinfo, 1); x1_type = get_fn_expr_argtype(fcinfo->flinfo, 3); if (!OidIsValid(x_type)||!OidIsValid(x0_type)||!OidIsValid(x1_type)) { elog(ERROR, "could not determine argument data types"); } if ( x_type!=x0_type || x_type!=x1_type ) { elog(ERROR, "abscissa types unequal"); } /* The ordinate (y) arguments are specifically declared in the SQL * function declaration. Here we just check and insist they are * identical. */ y0_type = get_fn_expr_argtype(fcinfo->flinfo, 2); y1_type = get_fn_expr_argtype(fcinfo->flinfo, 4); if ( y0_type != y1_type ) { elog(ERROR, "mismatched ordinate types"); } switch (x_type) { case INT8OID: { float8 x = (float8)PG_GETARG_INT64(0); float8 x0 = (float8)PG_GETARG_INT64(1); float8 x1 = (float8)PG_GETARG_INT64(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case INT4OID: { float8 x = (float8)PG_GETARG_INT32(0); float8 x0 = (float8)PG_GETARG_INT32(1); float8 x1 = (float8)PG_GETARG_INT32(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case INT2OID: { float8 x = (float8)PG_GETARG_INT16(0); float8 x0 = (float8)PG_GETARG_INT16(1); float8 x1 = (float8)PG_GETARG_INT16(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case FLOAT4OID: { float8 x = (float8)PG_GETARG_FLOAT4(0); float8 x0 = (float8)PG_GETARG_FLOAT4(1); float8 x1 = (float8)PG_GETARG_FLOAT4(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case FLOAT8OID: { float8 x = PG_GETARG_FLOAT8(0); float8 x0 = PG_GETARG_FLOAT8(1); float8 x1 = PG_GETARG_FLOAT8(3); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x == x0 ); } else p = (x-x0)/(x1-x0); } break; case DATEOID: { DateADT x = PG_GETARG_DATEADT(0); DateADT x0 = PG_GETARG_DATEADT(1); DateADT x1 = PG_GETARG_DATEADT(3); int32 x_x0 = date_diff(x, x0); int32 x1_x0 = date_diff(x1, x0); if ( x1 == x0 ) { eq_bounds = true; eq_abscissas = ( x_x0 == 0 ); } else p = ((float8)x_x0)/((float8)x1_x0); } break; case TIMEOID: { TimeADT x = PG_GETARG_TIMEADT(0); TimeADT x0 = PG_GETARG_TIMEADT(1); TimeADT x1 = PG_GETARG_TIMEADT(3); p = time_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case TIMESTAMPOID: { Timestamp x = PG_GETARG_TIMESTAMP(0); Timestamp x0 = PG_GETARG_TIMESTAMP(1); Timestamp x1 = PG_GETARG_TIMESTAMP(3); p = timestamp_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case TIMESTAMPTZOID: { TimestampTz x = PG_GETARG_TIMESTAMPTZ(0); TimestampTz x0 = PG_GETARG_TIMESTAMPTZ(1); TimestampTz x1 = PG_GETARG_TIMESTAMPTZ(3); p = timestamptz_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case INTERVALOID: { Interval * x = PG_GETARG_INTERVAL_P(0); Interval * x0 = PG_GETARG_INTERVAL_P(1); Interval * x1 = PG_GETARG_INTERVAL_P(3); p = interval_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; case NUMERICOID: { Numeric x = PG_GETARG_NUMERIC(0); Numeric x0 = PG_GETARG_NUMERIC(1); Numeric x1 = PG_GETARG_NUMERIC(3); p = numeric_li_fraction(x, x0, x1, &eq_bounds, &eq_abscissas); } break; default: elog(ERROR, "abscissa type not supported"); } if ( p_eq_bounds ) *p_eq_bounds = eq_bounds; if ( p_eq_abscissas ) *p_eq_abscissas = eq_abscissas; return p; }
/* Clause 3.3.1.3 */ Datum MarketWatchFrame1(PG_FUNCTION_ARGS) { int i; int status = 0; double old_mkt_cap = 0.0; double new_mkt_cap = 0.0; double pct_change = 0.0; struct pg_tm tt, *tm = &tt; int64 acct_id = PG_GETARG_INT64(0); int64 cust_id = PG_GETARG_INT64(1); int64 ending_co_id = PG_GETARG_INT64(2); char *industry_name_p = (char *) PG_GETARG_TEXT_P(3); DateADT start_date_p = PG_GETARG_DATEADT(4); int64 starting_co_id = PG_GETARG_INT64(5); int ret; TupleDesc tupdesc; SPITupleTable *tuptable = NULL; HeapTuple tuple = NULL; Datum result; char buf[MAXDATELEN + 1]; char industry_name[IN_NAME_LEN + 1]; char sql[2048] = ""; j2date(start_date_p + POSTGRES_EPOCH_JDATE, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); EncodeDateOnly(tm, DateStyle, buf); strcpy(industry_name, DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(industry_name_p)))); #ifdef DEBUG dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name, buf, starting_co_id); #endif SPI_connect(); if (cust_id != 0) { sprintf(sql, MWF1_1, cust_id); } else if (industry_name[0] != '\0') { sprintf(sql, MWF1_2, industry_name, starting_co_id, ending_co_id); } else if (acct_id != 0) { sprintf(sql, MWF1_3, acct_id); } else { status = BAD_INPUT_DATA; } #ifdef DEBUG elog(NOTICE, "SQL\n%s", sql); #endif /* DEBUG */ ret = SPI_exec(sql, 0); if (ret != SPI_OK_SELECT) { dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name, buf, starting_co_id); FAIL_FRAME(sql); } if (status != BAD_INPUT_DATA) { int count = SPI_processed; TupleDesc tupdesc4; SPITupleTable *tuptable4 = NULL; HeapTuple tuple4 = NULL; char *symbol; char *new_price; char *old_price; char *s_num_out; tupdesc = SPI_tuptable->tupdesc; tuptable = SPI_tuptable; for (i = 0; i < count; i++) { tuple = tuptable->vals[i]; symbol = SPI_getvalue(tuple, tupdesc, 1); #ifdef DEBUG elog(NOTICE, " symbol = '%s'", symbol); #endif /* DEBUG */ sprintf(sql, MWF1_4, symbol); #ifdef DEBUG elog(NOTICE, "SQL\n%s", sql); #endif /* DEBUG */ ret = SPI_exec(sql, 0); if (ret != SPI_OK_SELECT || SPI_processed == 0) { dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name, buf, starting_co_id); FAIL_FRAME(sql); continue; } tupdesc4 = SPI_tuptable->tupdesc; tuptable4 = SPI_tuptable; tuple4 = tuptable4->vals[0]; new_price = SPI_getvalue(tuple4, tupdesc4, 1); #ifdef DEBUG elog(NOTICE, " new_price = %s", new_price); elog(NOTICE, " new_price = %f", atof(new_price)); #endif /* DEBUG */ sprintf(sql, MWF1_5, symbol); #ifdef DEBUG elog(NOTICE, "SQL\n%s", sql); #endif /* DEBUG */ ret = SPI_exec(sql, 0); if (ret != SPI_OK_SELECT) { dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name, buf, starting_co_id); elog(NOTICE, "ERROR: sql not ok = %d", ret); } tupdesc4 = SPI_tuptable->tupdesc; tuptable4 = SPI_tuptable; tuple4 = tuptable4->vals[0]; s_num_out = SPI_getvalue(tuple4, tupdesc4, 1); #ifdef DEBUG elog(NOTICE, " s_num_out = %s", s_num_out); #endif /* DEBUG */ sprintf(sql, MWF1_6, symbol, pstrdup(buf)); #ifdef DEBUG elog(NOTICE, "SQL\n%s", sql); #endif /* DEBUG */ ret = SPI_exec(sql, 0); if (ret != SPI_OK_SELECT) { dump_mwf1_inputs(acct_id, cust_id, ending_co_id, industry_name, buf, starting_co_id); FAIL_FRAME(sql); } if (SPI_processed == 0) { elog(NOTICE, "No rows returned for getting old_price."); } else { tupdesc4 = SPI_tuptable->tupdesc; tuptable4 = SPI_tuptable; tuple4 = tuptable4->vals[0]; old_price = SPI_getvalue(tuple4, tupdesc4, 1); #ifdef DEBUG elog(NOTICE, " old_price = %s", old_price); elog(NOTICE, " old_price = %f", atof(old_price)); #endif /* DEBUG */ old_mkt_cap += atof(s_num_out) * atof(old_price); } new_mkt_cap += atof(s_num_out) * atof(new_price); #ifdef DEBUG elog(NOTICE, "old_mkt_cap = %f", old_mkt_cap); elog(NOTICE, "new_mkt_cap = %f", new_mkt_cap); #endif /* DEBUG */ } pct_change = 100.0 * (new_mkt_cap / old_mkt_cap - 1.0); #ifdef DEBUG elog(NOTICE, "pct_change = %f", pct_change); #endif /* DEBUG */ } #ifdef DEBUG elog(NOTICE, "MWF1 OUT: 1 %f", pct_change); #endif /* DEBUG */ SPI_finish(); result = DirectFunctionCall1(float8_numeric, Float8GetDatum(pct_change)); PG_RETURN_NUMERIC(result); }