On Wed, Jan 12, 2005 at 09:17:33PM -0500, Tom Lane wrote:
> I notice that the backend seems to have been using some nonstandard C
> code:
> 
> Error while reading shared library symbols:
> /home/markw/dbt2/storedproc/pgsql/c/../../../storedproc/pgsql/c/funcs.so: No 
> such file or directory.
> 
> What is that, and how much confidence have you got in it?

That's my C stored function library.  I'll attached it if anyone wants
to take a persusal.  Well, it was my first attempt with C stored
functions and SPI calls, so it wouldn't surprise me if it was flawed.
Would supplying the .so help the debugging?

Mark
/*
 * This file is released under the terms of the Artistic License.  Please see
 * the file LICENSE, included in this package, for details.
 *
 * Copyright (C) 2003 Mark Wong & Open Source Development Lab, Inc.
 *
 * Based on TPC-C Standard Specification Revision 5.0 Clause 2.8.2.
 */

#include <sys/types.h>
#include <unistd.h>
#include <postgres.h>
#include <fmgr.h>
#include <executor/spi.h>

/*
#define DEBUG
*/

#define DELIVERY_1 \
        "SELECT no_o_id\n" \
        "FROM new_order\n" \
        "WHERE no_w_id = %d\n" \
        "  AND no_d_id = %d"

#define DELIVERY_2 \
        "DELETE FROM new_order\n" \
        "WHERE no_o_id = %s\n" \
        "  AND no_w_id = %d\n" \
        "  AND no_d_id = %d"

#define DELIVERY_3 \
        "SELECT o_c_id\n" \
        "FROM orders\n" \
        "WHERE o_id = %s\n" \
        "  AND o_w_id = %d\n" \
        "  AND o_d_id = %d"

#define DELIVERY_4 \
        "UPDATE orders\n" \
        "SET o_carrier_id = %d\n" \
        "WHERE o_id = %s\n" \
        "  AND o_w_id = %d\n" \
        "  AND o_d_id = %d"

#define DELIVERY_5 \
        "UPDATE order_line\n" \
        "SET ol_delivery_d = current_timestamp\n" \
        "WHERE ol_o_id = %s\n" \
        "  AND ol_w_id = %d\n" \
        "  AND ol_d_id = %d"

#define DELIVERY_6 \
        "SELECT SUM(ol_amount * ol_quantity)\n" \
        "FROM order_line\n" \
        "WHERE ol_o_id = %s\n" \
        "  AND ol_w_id = %d\n" \
        "  AND ol_d_id = %d"

#define DELIVERY_7 \
        "UPDATE customer\n" \
        "SET c_delivery_cnt = c_delivery_cnt + 1,\n" \
        "    c_balance = c_balance + %s\n" \
        "WHERE c_id = %s\n" \
        "  AND c_w_id = %d\n" \
        "  AND c_d_id = %d"

#define NEW_ORDER_1 \
        "SELECT w_tax\n" \
        "FROM warehouse\n" \
        "WHERE w_id = %d"

#define NEW_ORDER_2 \
        "SELECT d_tax, d_next_o_id\n" \
        "FROM district \n" \
        "WHERE d_w_id = %d\n" \
        "  AND d_id = %d\n" \
        "FOR UPDATE"

#define NEW_ORDER_3 \
        "UPDATE district\n" \
        "SET d_next_o_id = d_next_o_id + 1\n" \
        "WHERE d_w_id = %d\n" \
        "  AND d_id = %d"

#define NEW_ORDER_4 \
        "SELECT c_discount, c_last, c_credit\n" \
        "FROM customer\n" \
        "WHERE c_w_id = %d\n" \
        "  AND c_d_id = %d\n" \
        "  AND c_id = %d"

#define NEW_ORDER_5 \
        "INSERT INTO new_order (no_o_id, no_w_id, no_d_id)\n" \
        "VALUES (%s, %d, %d)"

#define NEW_ORDER_6 \
        "INSERT INTO orders (o_id, o_d_id, o_w_id, o_c_id, o_entry_d,\n" \
        "                    o_carrier_id, o_ol_cnt, o_all_local)\n" \
        "VALUES (%s, %d, %d, %d, current_timestamp, NULL, %d, %d)"

#define NEW_ORDER_7 \
        "SELECT i_price, i_name, i_data\n" \
        "FROM item\n" \
        "WHERE i_id = %d"

#define NEW_ORDER_8 \
        "SELECT s_quantity, %s, s_data\n" \
        "FROM stock\n" \
        "WHERE s_i_id = %d\n" \
        "  AND s_w_id = %d"

#define NEW_ORDER_9 \
        "UPDATE stock\n" \
        "SET s_quantity = s_quantity - %d\n" \
        "WHERE s_i_id = %d\n" \
        "  AND s_w_id = %d"

#define NEW_ORDER_10 \
        "INSERT INTO order_line (ol_o_id, ol_d_id, ol_w_id, ol_number,\n" \
        "                        ol_i_id, ol_supply_w_id, ol_delivery_d,\n" \
        "                        ol_quantity, ol_amount, ol_dist_info)\n" \
        "VALUES (%s, %d, %d, %d, %d, %d, NULL, %d, %f, '%s')"

#define ORDER_STATUS_1 \
        "SELECT c_id\n" \
        "FROM customer\n" \
        "WHERE c_w_id = %d\n" \
        "  AND c_d_id = %d\n" \
        "  AND c_last = '%s'\n" \
        "ORDER BY c_first ASC"

#define ORDER_STATUS_2 \
        "SELECT c_first, c_middle, c_last, c_balance\n" \
        "FROM customer\n" \
        "WHERE c_w_id = %d\n" \
        "  AND c_d_id = %d\n" \
        "  AND c_id = %d"

#define ORDER_STATUS_3 \
        "SELECT o_id, o_carrier_id, o_entry_d, o_ol_cnt\n" \
        "FROM orders\n" \
        "WHERE o_w_id = %d\n" \
        "  AND o_d_id = %d \n" \
        "  AND o_c_id = %d\n" \
        "ORDER BY o_id DESC"

#define ORDER_STATUS_4 \
        "SELECT ol_i_id, ol_supply_w_id, ol_quantity, ol_amount,\n" \
        "       ol_delivery_d\n" \
        "FROM order_line\n" \
        "WHERE ol_w_id = %d\n" \
        "  AND ol_d_id = %d\n" \
        "  AND ol_o_id = %s"

#define PAYMENT_1 \
        "SELECT w_name, w_street_1, w_street_2, w_city, w_state, w_zip\n" \
        "FROM warehouse\n" \
        "WHERE w_id = %d"

#define PAYMENT_2 \
        "UPDATE warehouse\n" \
        "SET w_ytd = w_ytd + %f\n" \
        "WHERE w_id = %d"

#define PAYMENT_3 \
        "SELECT d_name, d_street_1, d_street_2, d_city, d_state, d_zip\n" \
        "FROM district\n" \
        "WHERE d_id = %d\n" \
        "  AND d_w_id = %d"

#define PAYMENT_4 \
        "UPDATE district\n" \
        "SET d_ytd = d_ytd + %f\n" \
        "WHERE d_id = %d\n" \
        "  AND d_w_id = %d"

#define PAYMENT_5 \
        "SELECT c_id\n" \
        "FROM customer\n" \
        "WHERE c_w_id = %d\n" \
        "  AND c_d_id = %d\n" \
        "  AND c_last = '%s'\n" \
        "ORDER BY c_first ASC"

#define PAYMENT_6 \
        "SELECT c_first, c_middle, c_last, c_street_1, c_street_2, c_city,\n" \
        "       c_state, c_zip, c_phone, c_since, c_credit,\n" \
        "       c_credit_lim, c_discount, c_balance, c_data, c_ytd_payment\n" \
        "FROM customer\n" \
        "WHERE c_w_id = %d\n" \
        "  AND c_d_id = %d\n" \
        "  AND c_id = %d"

#define PAYMENT_7_GC \
        "UPDATE customer\n" \
        "SET c_balance = c_balance - %f,\n" \
        "    c_ytd_payment = c_ytd_payment + 1\n" \
        "WHERE c_id = %d\n" \
        "  AND c_w_id = %d\n" \
        "  AND c_d_id = %d"

#define PAYMENT_7_BC \
        "UPDATE customer\n" \
        "SET c_balance = c_balance - %f,\n" \
        "    c_ytd_payment = c_ytd_payment + 1,\n" \
        "    c_data = '%s'\n" \
        "WHERE c_id = %d\n" \
        "  AND c_w_id = %d\n" \
        "  AND c_d_id = %d"

#define PAYMENT_8 \
        "INSERT INTO history (h_c_id, h_c_d_id, h_c_w_id, h_d_id, h_w_id,\n" \
        "                     h_date, h_amount, h_data)\n" \
        "VALUES (%d, %d, %d, %d, %d, current_timestamp, %f, '%s    %s')"

#define STOCK_LEVEL_1 \
        "SELECT d_next_o_id\n" \
        "FROM district\n" \
        "WHERE d_w_id = %d\n" \
        "AND d_id = %d"

#define STOCK_LEVEL_2 \
        "SELECT count(*)\n" \
        "FROM order_line, stock, district\n" \
        "WHERE d_id = %d\n" \
        "  AND d_w_id = %d\n" \
        "  AND d_id = ol_d_id\n" \
        "  AND d_w_id = ol_w_id\n" \
        "  AND ol_i_id = s_i_id\n" \
        "  AND ol_w_id = s_w_id\n" \
        "  AND s_quantity < %d\n" \
        "  AND ol_o_id BETWEEN (%d)\n" \
        "                 AND (%d)"

/* Prototypes to prevent potential gcc warnings. */

Datum delivery(PG_FUNCTION_ARGS);
Datum new_order(PG_FUNCTION_ARGS);
Datum order_status(PG_FUNCTION_ARGS);
Datum payment(PG_FUNCTION_ARGS);
Datum stock_level(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(delivery);
PG_FUNCTION_INFO_V1(new_order);
PG_FUNCTION_INFO_V1(order_status);
PG_FUNCTION_INFO_V1(payment);
PG_FUNCTION_INFO_V1(stock_level);

const char s_dist[10][11] = {
        "s_dist_01", "s_dist_02", "s_dist_03", "s_dist_04", "s_dist_05",
        "s_dist_06", "s_dist_07", "s_dist_08", "s_dist_09", "s_dist_10"
};

void escape_str(char *orig_str, char *esc_str)
{
        int i, j;
        for (i = 0, j = 0; i < strlen(orig_str); i++) {
                if (orig_str[i] == '\'') {
                        esc_str[j++] = '\'';
                } else if (orig_str[i] == '\\') {
                        esc_str[j++] = '\\';
                } else if (orig_str[i] == ')') {
                        esc_str[j++] = '\\';
                }
                esc_str[j++] = orig_str[i];
        }
        esc_str[j] = '\0';
}

Datum delivery(PG_FUNCTION_ARGS)
{
        /* Input variables. */
        int32 w_id = PG_GETARG_INT32(0);
        int32 o_carrier_id = PG_GETARG_INT32(1);

        TupleDesc tupdesc;
        SPITupleTable *tuptable;
        HeapTuple tuple;

        char query[256];
        int d_id;
        int ret;
        char *no_o_id = NULL;
        char *o_c_id = NULL;
        char *ol_amount = NULL;

        SPI_connect();

        for (d_id = 1; d_id <= 10; d_id++) {
                sprintf(query, DELIVERY_1, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                        tupdesc = SPI_tuptable->tupdesc;
                        tuptable = SPI_tuptable;
                        tuple = tuptable->vals[0];

                        no_o_id = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                        elog(NOTICE, "no_o_id = %s", no_o_id);
#endif /* DEBUG */
                } else {
                        /* Nothing to delivery for this district, try next. */
                        continue;
                }

                sprintf(query, DELIVERY_2, no_o_id, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_DELETE) {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }

                sprintf(query, DELIVERY_3, no_o_id, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                        tupdesc = SPI_tuptable->tupdesc;
                        tuptable = SPI_tuptable;
                        tuple = tuptable->vals[0];

                        o_c_id = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                        elog(NOTICE, "o_c_id = %s", no_o_id);
#endif /* DEBUG */
                } else {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }

                sprintf(query, DELIVERY_4, o_carrier_id, no_o_id, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_UPDATE) {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }

                sprintf(query, DELIVERY_5, no_o_id, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_UPDATE) {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }

                sprintf(query, DELIVERY_6, no_o_id, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                        tupdesc = SPI_tuptable->tupdesc;
                        tuptable = SPI_tuptable;
                        tuple = tuptable->vals[0];

                        ol_amount = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                        elog(NOTICE, "ol_amount = %s", no_o_id);
#endif /* DEBUG */
                } else {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }

                sprintf(query, DELIVERY_7, ol_amount, o_c_id, w_id, d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_UPDATE) {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }
        }

        SPI_finish();
        PG_RETURN_INT32(1);
}

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++) {
                ol_i_id[i] = PG_GETARG_INT32(j++);
                ol_supply_w_id[i] = PG_GETARG_INT32(j++);
                ol_quantity[i] = PG_GETARG_INT32(j++);
        }

#ifdef DEBUG
        elog(NOTICE, "%d w_id = %d", (int) getpid(), w_id);
        elog(NOTICE, "%d d_id = %d", (int) getpid(), d_id);
        elog(NOTICE, "%d c_id = %d", (int) getpid(), c_id);
        elog(NOTICE, "%d o_all_local = %d", (int) getpid(), o_all_local);
        elog(NOTICE, "%d o_ol_cnt = %d", (int) getpid(), o_ol_cnt);

        elog(NOTICE, "%d ##  ol_i_id  ol_supply_w_id  ol_quantity",
                (int) getpid());
        elog(NOTICE, "%d --  -------  --------------  -----------",
                (int) getpid());
        for (i = 0; i < o_ol_cnt; i++) {
                elog(NOTICE, "%d %2d  %7d  %14d  %11d",
                        (int) getpid(), i + 1, ol_i_id[i],
                        ol_supply_w_id[i], ol_quantity[i]);
        }
#endif /* DEBUG */

        SPI_connect();

        sprintf(query, NEW_ORDER_1, w_id);
#ifdef DEBUG
        elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
        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);
#ifdef DEBUG
                elog(NOTICE, "%d w_tax = %s", (int) getpid(), w_tax);
#endif /* DEBUG */
        } else {
                elog(NOTICE, "NEW_ORDER_1 failed");
                SPI_finish();
                PG_RETURN_INT32(10);
        }

        sprintf(query, NEW_ORDER_2, w_id, d_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        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);
#ifdef DEBUG
                elog(NOTICE, "%d d_tax = %s", (int) getpid(), d_tax);
                elog(NOTICE, "%d d_next_o_id = %s", (int) getpid(),
                        d_next_o_id);
#endif /* DEBUG */
        } else {
                elog(NOTICE, "NEW_ORDER_2 failed");
                SPI_finish();
                PG_RETURN_INT32(11);
        }

        sprintf(query, NEW_ORDER_3, w_id, d_id);
#ifdef DEBUG
        elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret != SPI_OK_UPDATE) {
                elog(NOTICE, "NEW_ORDER_3 failed");
                SPI_finish();
                PG_RETURN_INT32(12);
        }

        sprintf(query, NEW_ORDER_4, w_id, d_id, c_id);
#ifdef DEBUG
        elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
        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);
#ifdef DEBUG
                elog(NOTICE, "%d c_discount = %s", (int) getpid(), c_discount);
                elog(NOTICE, "%d c_last = %s", (int) getpid(), c_last);
                elog(NOTICE, "%d c_credit = %s", (int) getpid(), c_credit);
#endif /* DEBUG */
        } else {
                elog(NOTICE, "NEW_ORDER_4 failed");
                SPI_finish();
                PG_RETURN_INT32(13);
        }

        sprintf(query, NEW_ORDER_5, d_next_o_id, w_id, d_id);
#ifdef DEBUG
        elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret != SPI_OK_INSERT) {
                elog(NOTICE, "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);
#ifdef DEBUG
        elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret != SPI_OK_INSERT) {
                elog(NOTICE, "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]);
#ifdef DEBUG
                elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
                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);
#ifdef DEBUG
                        elog(NOTICE, "%d i_price[%d] = %s", (int) getpid(), i,
                                i_price[i]);
                        elog(NOTICE, "%d i_name[%d] = %s", (int) getpid(), i,
                                i_name[i]);
                        elog(NOTICE, "%d i_data[%d] = %s", (int) getpid(), i,
                                i_data[i]);
#endif /* DEBUG */
                } 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);
#ifdef DEBUG
                elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
                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);
#ifdef DEBUG
                        elog(NOTICE, "%d s_quantity[%d] = %s", (int) getpid(),
                                i, s_quantity[i]);
                        elog(NOTICE, "%d my_s_dist[%d] = %s", (int) getpid(),
                                i, my_s_dist[i]);
                        elog(NOTICE, "%d s_data[%d] = %s", (int) getpid(), i,
                                s_data[i]);
#endif /* DEBUG */
                } else {
                        elog(NOTICE, "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);
                }
#ifdef DEBUG
                elog(NOTICE, "%d %s", (int) getpid(), query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_UPDATE) {
                        elog(NOTICE, "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]);
#ifdef DEBUG
                elog(NOTICE, "%d %s", getpid(), query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_INSERT) {
                        elog(NOTICE, "NEW_ORDER_10 failed");
                        SPI_finish();
                        PG_RETURN_INT32(18);
                }
        }

        SPI_finish();
        PG_RETURN_INT32(0);
}

Datum order_status(PG_FUNCTION_ARGS)
{
        /* Input variables. */
        int32 c_id = PG_GETARG_INT32(0);
        int32 c_w_id = PG_GETARG_INT32(1);
        int32 c_d_id = PG_GETARG_INT32(2);
        text *c_last = PG_GETARG_TEXT_P(3);

        TupleDesc tupdesc;
        SPITupleTable *tuptable;
        HeapTuple tuple;

        int ret;
        int count;
        int j;
        char query[512];

        char *tmp_c_id;
        int my_c_id = 0;

        char *c_first = NULL;
        char *c_middle = NULL;
        char *my_c_last = NULL;
        char *c_balance = NULL;

        char *o_id = NULL;
        char *o_carrier_id = NULL;
        char *o_entry_d = NULL;
        char *o_ol_cnt = NULL;

        char *ol_i_id[15];
        char *ol_supply_w_id[15];
        char *ol_quantity[15];
        char *ol_amount[15];
        char *ol_delivery_d[15];

        SPI_connect();

        if (c_id == 0) {
                sprintf(query, ORDER_STATUS_1, c_w_id, c_d_id,
                        DatumGetCString(DirectFunctionCall1(textout,
                        PointerGetDatum(c_last))));
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                count = SPI_processed;
                if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                        tupdesc = SPI_tuptable->tupdesc;
                        tuptable = SPI_tuptable;
                        tuple = tuptable->vals[count / 2];

                        tmp_c_id = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                        elog(NOTICE, "c_id = %s, %d total, selected %d",
                                tmp_c_id, count, count / 2);
#endif /* DEBUG */
                        my_c_id = atoi(tmp_c_id);
                } else {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }
        } else {
                my_c_id = c_id;
        }

        sprintf(query, ORDER_STATUS_2, c_w_id, c_d_id, my_c_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        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_first = SPI_getvalue(tuple, tupdesc, 1);
                c_middle = SPI_getvalue(tuple, tupdesc, 2);
                my_c_last = SPI_getvalue(tuple, tupdesc, 3);
                c_balance = SPI_getvalue(tuple, tupdesc, 4);
#ifdef DEBUG
                elog(NOTICE, "c_first = %s", c_first);
                elog(NOTICE, "c_middle = %s", c_middle);
                elog(NOTICE, "c_last = %s", my_c_last);
                elog(NOTICE, "c_balance = %s", c_balance);
#endif /* DEBUG */
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        /* Maybe this should be a join with the previous query. */
        sprintf(query, ORDER_STATUS_3, c_w_id, c_d_id, my_c_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                tupdesc = SPI_tuptable->tupdesc;
                tuptable = SPI_tuptable;
                tuple = tuptable->vals[0];

                o_id = SPI_getvalue(tuple, tupdesc, 1);
                o_carrier_id = SPI_getvalue(tuple, tupdesc, 2);
                o_entry_d = SPI_getvalue(tuple, tupdesc, 3);
                o_ol_cnt = SPI_getvalue(tuple, tupdesc, 4);
#ifdef DEBUG
                elog(NOTICE, "o_id = %s", o_id);
                elog(NOTICE, "o_carrier_id = %s", o_carrier_id);
                elog(NOTICE, "o_entry_d = %s", o_entry_d);
                elog(NOTICE, "o_ol_cnt = %s", o_ol_cnt);
#endif /* DEBUG */
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        sprintf(query, ORDER_STATUS_4, c_w_id, c_d_id, o_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        count = SPI_processed;
#ifdef DEBUG
        elog(NOTICE, "##  ol_i_id  ol_supply_w_id  ol_quantity  ol_amount  
ol_delivery_d");
        elog(NOTICE, "--  -------  --------------  -----------  ---------  
-------------");
#endif /* DEBUG */
        if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                tupdesc = SPI_tuptable->tupdesc;
                tuptable = SPI_tuptable;

                for (j = 0; j < count; j++) {
                        tuple = tuptable->vals[j];

                        ol_i_id[j] = SPI_getvalue(tuple, tupdesc, 1);
                        ol_supply_w_id[j] = SPI_getvalue(tuple, tupdesc, 2);
                        ol_quantity[j] = SPI_getvalue(tuple, tupdesc, 3);
                        ol_amount[j] = SPI_getvalue(tuple, tupdesc, 4);
                        ol_delivery_d[j] = SPI_getvalue(tuple, tupdesc, 5);
#ifdef DEBUG
                        elog(NOTICE, "%2d  %7s  %14s  %11s  %9.2f  %13s",
                                j + 1, ol_i_id[j], ol_supply_w_id[j],
                                ol_quantity[j], atof(ol_amount[j]),
                                ol_delivery_d[j]);
#endif /* DEBUG */
                }
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        SPI_finish();
        PG_RETURN_INT32(1);
}

Datum payment(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 c_w_id = PG_GETARG_INT32(3);
        int32 c_d_id = PG_GETARG_INT32(4);
        text *c_last = PG_GETARG_TEXT_P(5);
        float4 h_amount = PG_GETARG_FLOAT4(6);

        TupleDesc tupdesc;
        SPITupleTable *tuptable;
        HeapTuple tuple;

        int ret;
        char query[4096];
        char *w_name = NULL;
        char *w_street_1 = NULL;
        char *w_street_2 = NULL;
        char *w_city = NULL;
        char *w_state = NULL;
        char *w_zip = NULL;

        char *d_name = NULL;
        char *d_street_1 = NULL;
        char *d_street_2 = NULL;
        char *d_city = NULL;
        char *d_state = NULL;
        char *d_zip = NULL;

        char *tmp_c_id = NULL;
        int my_c_id = 0;
        int count;

        char *c_first = NULL;
        char *c_middle = NULL;
        char *my_c_last = NULL;
        char *c_street_1 = NULL;
        char *c_street_2 = NULL;
        char *c_city = NULL;
        char *c_state = NULL;
        char *c_zip = NULL;
        char *c_phone = NULL;
        char *c_since = NULL;
        char *c_credit = NULL;
        char *c_credit_lim = NULL;
        char *c_discount = NULL;
        char *c_balance = NULL;
        char *c_data = NULL;
        char *c_ytd_payment = NULL;

        char my_w_name[20];
        char my_d_name[20];

#ifdef DEBUG
        elog(NOTICE, "w_id = %d", w_id);
        elog(NOTICE, "d_id = %d", d_id);
        elog(NOTICE, "c_id = %d", c_id);
        elog(NOTICE, "c_w_id = %d", c_w_id);
        elog(NOTICE, "c_d_id = %d", c_d_id);
        elog(NOTICE, "c_last = %s",
                DatumGetCString(DirectFunctionCall1(textout,
                PointerGetDatum(c_last))));
        elog(NOTICE, "h_amount = %f", h_amount);
#endif /* DEBUG */

        SPI_connect();

        sprintf(query, PAYMENT_1, w_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        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_name = SPI_getvalue(tuple, tupdesc, 1);
                w_street_1 = SPI_getvalue(tuple, tupdesc, 2);
                w_street_2 = SPI_getvalue(tuple, tupdesc, 3);
                w_city = SPI_getvalue(tuple, tupdesc, 4);
                w_state = SPI_getvalue(tuple, tupdesc, 5);
                w_zip = SPI_getvalue(tuple, tupdesc, 6);
#ifdef DEBUG
                elog(NOTICE, "w_name = %s", w_name);
                elog(NOTICE, "w_street_1 = %s", w_street_1);
                elog(NOTICE, "w_street_2 = %s", w_street_2);
                elog(NOTICE, "w_city = %s", w_city);
                elog(NOTICE, "w_state = %s", w_state);
                elog(NOTICE, "w_zip = %s", w_zip);
#endif /* DEBUG */
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        sprintf(query, PAYMENT_2, h_amount, w_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret != SPI_OK_UPDATE) {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        sprintf(query, PAYMENT_3, d_id, w_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        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_name = SPI_getvalue(tuple, tupdesc, 1);
                d_street_1 = SPI_getvalue(tuple, tupdesc, 2);
                d_street_2 = SPI_getvalue(tuple, tupdesc, 3);
                d_city = SPI_getvalue(tuple, tupdesc, 4);
                d_state = SPI_getvalue(tuple, tupdesc, 5);
                d_zip = SPI_getvalue(tuple, tupdesc, 6);
#ifdef DEBUG
                elog(NOTICE, "d_name = %s", d_name);
                elog(NOTICE, "d_street_1 = %s", d_street_1);
                elog(NOTICE, "d_street_2 = %s", d_street_2);
                elog(NOTICE, "d_city = %s", d_city);
                elog(NOTICE, "d_state = %s", d_state);
                elog(NOTICE, "d_zip = %s", d_zip);
#endif /* DEBUG */
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        sprintf(query, PAYMENT_4, h_amount, d_id, w_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret != SPI_OK_UPDATE) {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        if (c_id == 0) {
                sprintf(query, PAYMENT_5, w_id, d_id,
                        DatumGetCString(DirectFunctionCall1(textout,
                        PointerGetDatum(c_last))));
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                count = SPI_processed;
                if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                        tupdesc = SPI_tuptable->tupdesc;
                        tuptable = SPI_tuptable;
                        tuple = tuptable->vals[count / 2];

                        tmp_c_id = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                        elog(NOTICE, "c_id = %s, %d total, selected %d",
                                tmp_c_id, count, count / 2);
#endif /* DEBUG */
                        my_c_id = atoi(tmp_c_id);
                } else {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }
        } else {
                my_c_id = c_id;
        }

        sprintf(query, PAYMENT_6, c_w_id, c_d_id, my_c_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        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_first = SPI_getvalue(tuple, tupdesc, 1);
                c_middle = SPI_getvalue(tuple, tupdesc, 2);
                my_c_last = SPI_getvalue(tuple, tupdesc, 3);
                c_street_1 = SPI_getvalue(tuple, tupdesc, 4);
                c_street_2 = SPI_getvalue(tuple, tupdesc, 5);
                c_city = SPI_getvalue(tuple, tupdesc, 6);
                c_state = SPI_getvalue(tuple, tupdesc, 7);
                c_zip = SPI_getvalue(tuple, tupdesc, 8);
                c_phone = SPI_getvalue(tuple, tupdesc, 9);
                c_since = SPI_getvalue(tuple, tupdesc, 10);
                c_credit = SPI_getvalue(tuple, tupdesc, 11);
                c_credit_lim = SPI_getvalue(tuple, tupdesc, 12);
                c_discount = SPI_getvalue(tuple, tupdesc, 13);
                c_balance = SPI_getvalue(tuple, tupdesc, 14);
                c_data = SPI_getvalue(tuple, tupdesc, 15);
                c_ytd_payment = SPI_getvalue(tuple, tupdesc, 16);
#ifdef DEBUG
                elog(NOTICE, "c_first = %s", c_first);
                elog(NOTICE, "c_middle = %s", c_middle);
                elog(NOTICE, "c_last = %s", my_c_last);
                elog(NOTICE, "c_street_1 = %s", c_street_1);
                elog(NOTICE, "c_street_2 = %s", c_street_2);
                elog(NOTICE, "c_city = %s", c_city);
                elog(NOTICE, "c_state = %s", c_state);
                elog(NOTICE, "c_zip = %s", c_zip);
                elog(NOTICE, "c_phone = %s", c_phone);
                elog(NOTICE, "c_since = %s", c_since);
                elog(NOTICE, "c_credit = %s", c_credit);
                elog(NOTICE, "c_credit_lim = %s", c_credit_lim);
                elog(NOTICE, "c_discount = %s", c_discount);
                elog(NOTICE, "c_balance = %s", c_balance);
                elog(NOTICE, "c_data = %s", c_data);
                elog(NOTICE, "c_ytd_payment = %s", c_ytd_payment);
#endif /* DEBUG */
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        /* It's either "BC" or "GC". */
        if (c_credit[0] == 'G') {
                sprintf(query, PAYMENT_7_GC, h_amount, my_c_id, c_w_id, c_d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_UPDATE) {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }
        } else {
                char my_c_data[1000];

                sprintf(my_c_data, "%d %d %d %d %d %f ", my_c_id, c_d_id,
                        c_w_id, d_id, w_id, h_amount);
                /* Copy and escape all at once! */
                escape_str(c_data, my_c_data);

                sprintf(query, PAYMENT_7_BC, h_amount, my_c_data, my_c_id,
                        c_w_id, c_d_id);
#ifdef DEBUG
                elog(NOTICE, "%s", query);
#endif /* DEBUG */
                ret = SPI_exec(query, 0);
                if (ret != SPI_OK_UPDATE) {
                        SPI_finish();
                        PG_RETURN_INT32(-1);
                }
        }

        /* Escape special characters. */
        escape_str(w_name, my_w_name);
        escape_str(d_name, my_d_name);

        sprintf(query, PAYMENT_8, my_c_id, c_d_id, c_w_id, d_id, w_id,
                h_amount, my_w_name, my_d_name);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret != SPI_OK_INSERT) {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        SPI_finish();
        PG_RETURN_INT32(1);
}

Datum stock_level(PG_FUNCTION_ARGS)
{
        /* Input variables. */
        int32 w_id = PG_GETARG_INT32(0);
        int32 d_id = PG_GETARG_INT32(1);
        int32 threshold = PG_GETARG_INT32(2);

        TupleDesc tupdesc;
        SPITupleTable *tuptable;
        HeapTuple tuple;

        int d_next_o_id = 0;
        int low_stock = 0;
        int ret;
        char query[256];
        char *buf;

        SPI_connect();

        sprintf(query, STOCK_LEVEL_1, w_id, d_id);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                tupdesc = SPI_tuptable->tupdesc;
                tuptable = SPI_tuptable;
                tuple = tuptable->vals[0];

                buf = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                elog(NOTICE, "d_next_o_id = %s", buf);
#endif /* DEBUG */
                d_next_o_id = atoi(buf);
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        sprintf(query, STOCK_LEVEL_2, w_id, d_id, threshold, d_next_o_id - 20,
                d_next_o_id - 1);
#ifdef DEBUG
        elog(NOTICE, "%s", query);
#endif /* DEBUG */
        ret = SPI_exec(query, 0);
        if (ret == SPI_OK_SELECT && SPI_processed > 0) {
                tupdesc = SPI_tuptable->tupdesc;
                tuptable = SPI_tuptable;
                tuple = tuptable->vals[0];

                buf = SPI_getvalue(tuple, tupdesc, 1);
#ifdef DEBUG
                elog(NOTICE, "low_stock = %s", buf);
#endif /* DEBUG */
                low_stock = atoi(buf);
        } else {
                SPI_finish();
                PG_RETURN_INT32(-1);
        }

        SPI_finish();
        PG_RETURN_INT32(low_stock);
}
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
      joining column's datatypes do not match

Reply via email to