Datum pgx_complex_divide(PG_FUNCTION_ARGS) { TupleDesc tupdesc; HeapTuple tuple; double re[2]; double im[2]; int i; double q; Datum datum[2]; bool isnull[2]; // build a tuple descriptor for our result type if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); // unwrap values. for (i = 0; i < 2; i++) { HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(i); bool isnull[2]; Datum dr, di; dr = GetAttributeByName(t, "re", &isnull[0]); di = GetAttributeByName(t, "im", &isnull[1]); // STRICT prevents the 'complex' value from being null but does // not prevent its components from being null. if (isnull[0] || isnull[1]) { PG_RETURN_NULL(); } re[i] = DatumGetFloat8(dr); im[i] = DatumGetFloat8(di); } // the denominator is the square of the magnitude of the divisor. q = re[1] * re[1] + im[1] * im[1]; // should I throw error instead of returning null? if (q == 0.0) { PG_RETURN_NULL(); } datum[0] = Float8GetDatum((re[0] * re[1] + im[0] * im[1]) / q); datum[1] = Float8GetDatum((im[0] * re[1] - im[1] * re[0]) / q); BlessTupleDesc(tupdesc); tuple = heap_form_tuple(tupdesc, datum, isnull); PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); }
Datum pgx_complex_norm(PG_FUNCTION_ARGS) { HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0); TupleDesc tupdesc; HeapTuple tuple; double re; double im; bool isnull[2]; Datum datum[2]; double m; // build a tuple descriptor for our result type if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("function returning record called in context " "that cannot accept type record"))); // unwrap values. datum[0] = GetAttributeByName(t, "re", &isnull[0]); datum[1] = GetAttributeByName(t, "im", &isnull[1]); // STRICT prevents the 'complex' value from being null but does // not prevent its components from being null. if (isnull[0] || isnull[1]) { PG_RETURN_NULL(); } re = DatumGetFloat8(datum[0]); im = DatumGetFloat8(datum[1]); m = hypot(re, im); // should I throw error instead of returning null? if (m == 0.0) { PG_RETURN_NULL(); } datum[0] = Float8GetDatum(re / m); datum[1] = Float8GetDatum(im / m); BlessTupleDesc(tupdesc); tuple = heap_form_tuple(tupdesc, datum, isnull); PG_RETURN_DATUM(HeapTupleGetDatum(tuple)); }
Datum overpaid(PG_FUNCTION_ARGS) { HeapTupleHeader tuple = PG_GETARG_HEAPTUPLEHEADER(0); bool isnull; int32 salary; salary = DatumGetInt32(GetAttributeByName(tuple, "salary", &isnull)); if (isnull) PG_RETURN_NULL(); PG_RETURN_BOOL(salary > 699); }
bool c_overpaid(TupleTableSlot *t, /* the current instance of EMP */ int32 limit) { bool isnull; int32 salary; salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); if (isnull) return (false); return salary > limit; }
bool c_overpaid(HeapTupleHeader t, /* the current instance of EMP */ int32 limit) { bool isnull; int32 salary; salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); if (isnull) return false; return salary > limit; }
Datum pgx_complex_near(PG_FUNCTION_ARGS) { double re[2]; double im[2]; double p, q; int i; // unwrap values. for (i = 0; i < 2; i++) { HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(i); bool isnull[2]; Datum dr = GetAttributeByName(t, "re", &isnull[0]); Datum di = GetAttributeByName(t, "im", &isnull[1]); // STRICT prevents the 'complex' value from being null but does // not prevent its components from being null. if (isnull[0] || isnull[1]) { PG_RETURN_NULL(); } re[i] = DatumGetFloat8(dr); im[i] = DatumGetFloat8(di); } // compute distance between points, distance of points from origin. p = hypot(re[0] - re[1], im[0] - im[1]); q = hypot(re[0], im[0]) + hypot(re[1], im[1]); if (q == 0) { PG_RETURN_BOOL(1); } // we consider the points 'near' each other if the distance between them is small // relative to the size of them. PG_RETURN_BOOL(p / q < 1e-8); }
Datum c_overpaid(PG_FUNCTION_ARGS) { HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(0); int32 limit = PG_GETARG_INT32(1); bool isnull; int32 salary; salary = DatumGetInt32(GetAttributeByName(t, "salary", &isnull)); if (isnull) PG_RETURN_BOOL(false); /* * Alternatively, we might prefer to do PG_RETURN_NULL() for null salary */ PG_RETURN_BOOL(salary > limit); }
Datum new_order(PG_FUNCTION_ARGS) { /* Input variables. */ int32 w_id = PG_GETARG_INT32(0); int32 d_id = PG_GETARG_INT32(1); int32 c_id = PG_GETARG_INT32(2); int32 o_all_local = PG_GETARG_INT32(3); int32 o_ol_cnt = PG_GETARG_INT32(4); TupleDesc tupdesc; SPITupleTable *tuptable; HeapTuple tuple; int32 ol_i_id[15]; int32 ol_supply_w_id[15]; int32 ol_quantity[15]; int i, j; int ret; char query[1024]; char *w_tax = NULL; char *d_tax = NULL; char *d_next_o_id = NULL; char *c_discount = NULL; char *c_last = NULL; char *c_credit = NULL; float order_amount = 0.0; char *i_price[15]; char *i_name[15]; char *i_data[15]; float ol_amount[15]; char *s_quantity[15]; char *my_s_dist[15]; char *s_data[15]; /* Loop through the last set of parameters. */ for (i = 0, j = 5; i < 15; i++) { bool isnull; HeapTupleHeader t = PG_GETARG_HEAPTUPLEHEADER(j++); ol_i_id[i] = DatumGetInt32(GetAttributeByName(t, "ol_i_id", &isnull)); ol_supply_w_id[i] = DatumGetInt32(GetAttributeByName(t, "ol_supply_w_id", &isnull)); ol_quantity[i] = DatumGetInt32(GetAttributeByName(t, "ol_quantity", &isnull)); } elog(DEBUG1, "%d w_id = %d", (int) getpid(), w_id); elog(DEBUG1, "%d d_id = %d", (int) getpid(), d_id); elog(DEBUG1, "%d c_id = %d", (int) getpid(), c_id); elog(DEBUG1, "%d o_all_local = %d", (int) getpid(), o_all_local); elog(DEBUG1, "%d o_ol_cnt = %d", (int) getpid(), o_ol_cnt); elog(DEBUG1, "%d ## ol_i_id ol_supply_w_id ol_quantity", (int) getpid()); elog(DEBUG1, "%d -- ------- -------------- -----------", (int) getpid()); for (i = 0; i < o_ol_cnt; i++) { elog(DEBUG1, "%d %2d %7d %14d %11d", (int) getpid(), i + 1, ol_i_id[i], ol_supply_w_id[i], ol_quantity[i]); } SPI_connect(); sprintf(query, NEW_ORDER_1, w_id); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret == SPI_OK_SELECT && SPI_processed > 0) { tupdesc = SPI_tuptable->tupdesc; tuptable = SPI_tuptable; tuple = tuptable->vals[0]; w_tax = SPI_getvalue(tuple, tupdesc, 1); elog(DEBUG1, "%d w_tax = %s", (int) getpid(), w_tax); } else { elog(WARNING, "NEW_ORDER_1 failed"); SPI_finish(); PG_RETURN_INT32(10); } sprintf(query, NEW_ORDER_2, w_id, d_id); elog(DEBUG1, "%s", query); ret = SPI_exec(query, 0); if (ret == SPI_OK_SELECT && SPI_processed > 0) { tupdesc = SPI_tuptable->tupdesc; tuptable = SPI_tuptable; tuple = tuptable->vals[0]; d_tax = SPI_getvalue(tuple, tupdesc, 1); d_next_o_id = SPI_getvalue(tuple, tupdesc, 2); elog(DEBUG1, "%d d_tax = %s", (int) getpid(), d_tax); elog(DEBUG1, "%d d_next_o_id = %s", (int) getpid(), d_next_o_id); } else { elog(WARNING, "NEW_ORDER_2 failed"); SPI_finish(); PG_RETURN_INT32(11); } sprintf(query, NEW_ORDER_3, w_id, d_id); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret != SPI_OK_UPDATE) { elog(WARNING, "NEW_ORDER_3 failed"); SPI_finish(); PG_RETURN_INT32(12); } sprintf(query, NEW_ORDER_4, w_id, d_id, c_id); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret == SPI_OK_SELECT && SPI_processed > 0) { tupdesc = SPI_tuptable->tupdesc; tuptable = SPI_tuptable; tuple = tuptable->vals[0]; c_discount = SPI_getvalue(tuple, tupdesc, 1); c_last = SPI_getvalue(tuple, tupdesc, 2); c_credit = SPI_getvalue(tuple, tupdesc, 3); elog(DEBUG1, "%d c_discount = %s", (int) getpid(), c_discount); elog(DEBUG1, "%d c_last = %s", (int) getpid(), c_last); elog(DEBUG1, "%d c_credit = %s", (int) getpid(), c_credit); } else { elog(WARNING, "NEW_ORDER_4 failed"); SPI_finish(); PG_RETURN_INT32(13); } sprintf(query, NEW_ORDER_5, d_next_o_id, w_id, d_id); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret != SPI_OK_INSERT) { elog(WARNING, "NEW_ORDER_5 failed %d", ret); SPI_finish(); PG_RETURN_INT32(14); } sprintf(query, NEW_ORDER_6, d_next_o_id, d_id, w_id, c_id, o_ol_cnt, o_all_local); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret != SPI_OK_INSERT) { elog(WARNING, "NEW_ORDER_6 failed"); SPI_finish(); PG_RETURN_INT32(15); } for (i = 0; i < o_ol_cnt; i++) { sprintf(query, NEW_ORDER_7, ol_i_id[i]); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); /* * Shouldn't have to check if ol_i_id is 0, but if the row * doesn't exist, the query still passes. */ if (ol_i_id[i] != 0 && ret == SPI_OK_SELECT && SPI_processed > 0) { tupdesc = SPI_tuptable->tupdesc; tuptable = SPI_tuptable; tuple = tuptable->vals[0]; i_price[i] = SPI_getvalue(tuple, tupdesc, 1); i_name[i] = SPI_getvalue(tuple, tupdesc, 2); i_data[i] = SPI_getvalue(tuple, tupdesc, 3); elog(DEBUG1, "%d i_price[%d] = %s", (int) getpid(), i, i_price[i]); elog(DEBUG1, "%d i_name[%d] = %s", (int) getpid(), i, i_name[i]); elog(DEBUG1, "%d i_data[%d] = %s", (int) getpid(), i, i_data[i]); } else { /* Item doesn't exist, rollback transaction. */ SPI_finish(); PG_RETURN_INT32(2); } ol_amount[i] = atof(i_price[i]) * (float) ol_quantity[i]; sprintf(query, NEW_ORDER_8, s_dist[d_id - 1], ol_i_id[i], w_id); elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret == SPI_OK_SELECT && SPI_processed > 0) { tupdesc = SPI_tuptable->tupdesc; tuptable = SPI_tuptable; tuple = tuptable->vals[0]; s_quantity[i] = SPI_getvalue(tuple, tupdesc, 1); my_s_dist[i] = SPI_getvalue(tuple, tupdesc, 2); s_data[i] = SPI_getvalue(tuple, tupdesc, 3); elog(DEBUG1, "%d s_quantity[%d] = %s", (int) getpid(), i, s_quantity[i]); elog(DEBUG1, "%d my_s_dist[%d] = %s", (int) getpid(), i, my_s_dist[i]); elog(DEBUG1, "%d s_data[%d] = %s", (int) getpid(), i, s_data[i]); } else { elog(WARNING, "NEW_ORDER_8 failed"); SPI_finish(); PG_RETURN_INT32(16); } order_amount += ol_amount[i]; if (atoi(s_quantity[i]) > ol_quantity[i] + 10) { sprintf(query, NEW_ORDER_9, ol_quantity[i], ol_i_id[i], w_id); } else { sprintf(query, NEW_ORDER_9, ol_quantity[i] - 91, ol_i_id[i], w_id); } elog(DEBUG1, "%d %s", (int) getpid(), query); ret = SPI_exec(query, 0); if (ret != SPI_OK_UPDATE) { elog(WARNING, "NEW_ORDER_9 failed"); SPI_finish(); PG_RETURN_INT32(17); } sprintf(query, NEW_ORDER_10, d_next_o_id, d_id, w_id, i + 1, ol_i_id[i], ol_supply_w_id[i], ol_quantity[i], ol_amount[i], my_s_dist[i]); elog(DEBUG1, "%d %s", getpid(), query); ret = SPI_exec(query, 0); if (ret != SPI_OK_INSERT) { elog(WARNING, "NEW_ORDER_10 failed"); SPI_finish(); PG_RETURN_INT32(18); } } SPI_finish(); PG_RETURN_INT32(0); }