Example #1
0
/*
 * load queue info from pgq.queue table.
 */
static void load_queue_info(Datum queue_name, struct QueueState *state)
{
	Datum values[1];
	int res;
	TupleDesc   desc;
	HeapTuple   row;
	bool isnull;

	values[0] = queue_name;
	res = SPI_execute_plan(queue_plan, values, NULL, false, 0);
	if (res != SPI_OK_SELECT)
		elog(ERROR, "Queue fetch failed");
	if (SPI_processed == 0)
		elog(ERROR, "No such queue");

	row = SPI_tuptable->vals[0];
	desc = SPI_tuptable->tupdesc;
	state->queue_id = DatumGetInt32(SPI_getbinval(row, desc, COL_QUEUE_ID, &isnull));
	if (isnull)
		elog(ERROR, "queue id NULL");
	state->cur_table = DatumGetInt32(SPI_getbinval(row, desc, COL_TBLNO, &isnull));
	if (isnull)
		elog(ERROR, "table nr NULL");
	state->table_prefix = SPI_getvalue(row, desc, COL_PREFIX);
	if (state->table_prefix == NULL)
		elog(ERROR, "table prefix NULL");
	state->next_event_id = SPI_getbinval(row, desc, COL_EVENT_ID, &isnull);
	if (isnull)
		elog(ERROR, "Seq name NULL");
}
Example #2
0
/*
 * helper for queue insertion.
 *
 * does not support NULL arguments.
 */
void pgq_simple_insert(const char *queue_name, Datum ev_type, Datum ev_data,
		       Datum ev_extra1, Datum ev_extra2, Datum ev_extra3, Datum ev_extra4)
{
	Datum values[7];
	char nulls[7];
	static void *plan = NULL;
	int res;

	if (!plan) {
		const char *sql;
		Oid   types[7] = { TEXTOID, TEXTOID, TEXTOID, TEXTOID, TEXTOID, TEXTOID, TEXTOID };

		sql = "select pgq.insert_event($1, $2, $3, $4, $5, $6, $7)";
		plan = SPI_saveplan(SPI_prepare(sql, 7, types));
		if (plan == NULL)
			elog(ERROR, "logtriga: SPI_prepare() failed");
	}
	values[0] = DirectFunctionCall1(textin, (Datum)queue_name);
	values[1] = ev_type;
	values[2] = ev_data;
	values[3] = ev_extra1;
	values[4] = ev_extra2;
	values[5] = ev_extra3;
	values[6] = ev_extra4;
	nulls[0] = ' ';
	nulls[1] = ev_type ? ' ' : 'n';
	nulls[2] = ev_data ? ' ' : 'n';
	nulls[3] = ev_extra1 ? ' ' : 'n';
	nulls[4] = ev_extra2 ? ' ' : 'n';
	nulls[5] = ev_extra3 ? ' ' : 'n';
	nulls[6] = ev_extra4 ? ' ' : 'n';
	res = SPI_execute_plan(plan, values, nulls, false, 0);
	if (res != SPI_OK_SELECT)
		elog(ERROR, "call of pgq.insert_event failed");
}
Example #3
0
/* execute prepared plan */
void
execute_plan(int expected, SPIPlanPtr plan, Datum *values, const char *nulls)
{
	int	ret = SPI_execute_plan(plan, values, nulls, false, 0);
	if EXEC_FAILED(ret, expected)
		elog(ERROR, "query failed: (code=%d, expected=%d)", ret, expected);
}
Example #4
0
/**
 * Create and run the basic query on the gridvalue table, for use by the wciReadFloat function
 */
static void runWciReadFloatQueryGrid(struct ReadStore * out, FuncCallContext * funcctx, FunctionCallInfo fcinfo)
{
	initializeGeos();

	struct WciReadParameterCollection p;
	parseReadParameters(& p, fcinfo);
	const char * whatToSelect = "value, dataprovidername, placename::text, placegeometry, referencetime, validtimefrom, validtimeto, validtimeindeterminatecode, valueparametername, valueunitname, levelparametername, levelunitname, levelfrom, levelto, levelindeterminatecode, dataversion, confidencecode, valuestoretime, valueid, valuetype, placeid";
	const char * gridQuery = build_query(& p, GridTable, OutputFloat, whatToSelect, NULL);
	elog(DEBUG1, gridQuery);

	// Perform primary query
	SPIPlanPtr queryPlan = getSpiPlan(gridQuery);
	if (SPI_OK_SELECT != SPI_execute_plan(queryPlan, NULL, NULL, true, 0))
	{
		ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg(
				"Error when performing base query")));
	}
	MemoryContext oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);


	if ( PG_ARGISNULL(1) )
	{
		ReadStoreGridReturnInit(out, SPI_tuptable, SPI_processed, NULL);
	}
	else
	{
		text * location_t = PG_GETARG_TEXT_P(1);
		const char * location = TextPGetCString(location_t);
		ReadStoreGridReturnInit(out, SPI_tuptable, SPI_processed, location);
	}
	MemoryContextSwitchTo(oldcontext);
}
Example #5
0
Datum
dbms_alert_signal(PG_FUNCTION_ARGS)
{
	void *plan;
	Oid argtypes[] = {TEXTOID, TEXTOID};
	Datum values[2];
	char nulls[2] = {' ',' '};

	if (PG_ARGISNULL(0))
		ereport(ERROR,
    			(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
        		 errmsg("event name is NULL"),
			 errdetail("Eventname may not be NULL.")));

	if (PG_ARGISNULL(1))
		nulls[1] = 'n';

	values[0] = PG_GETARG_DATUM(0);
	values[1] = PG_GETARG_DATUM(1);


	if (SPI_connect() < 0)
		ereport(ERROR,
			(errcode(ERRCODE_INTERNAL_ERROR),
			 errmsg("SPI_connect failed")));

	SPI_EXEC("SELECT 1 FROM pg_catalog.pg_class c "
                    "WHERE pg_catalog.pg_table_is_visible(c.oid) "
                            "AND c.relkind='r' AND c.relname = 'ora_alerts'", SELECT);
	if (0 == SPI_processed)
	{
		SPI_EXEC("CREATE TEMP TABLE ora_alerts(event text, message text)", UTILITY);
		SPI_EXEC("REVOKE ALL ON TABLE ora_alerts FROM PUBLIC", UTILITY);
		SPI_EXEC("CREATE CONSTRAINT TRIGGER ora_alert_signal AFTER INSERT ON ora_alerts "
    		    "INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE dbms_alert.defered_signal()", UTILITY);
	}


	if (!(plan = SPI_prepare(
			"INSERT INTO ora_alerts(event,message) VALUES($1, $2)",
			2,
			argtypes)))
			ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				 errmsg("SPI_prepare failed")));

	if (SPI_OK_INSERT != SPI_execute_plan(plan, values, nulls, false, 1))
			ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				errmsg("can't execute sql")));


	SPI_finish();
	PG_RETURN_VOID();
}
Example #6
0
File: file.c Project: 50wu/gpdb
/*
 * utl_file_dir security .. is solved with aux. table.
 *
 * Raise exception if don't find string in table.
 */
static void
check_secure_locality(const char *path)
{
	static SPIPlanPtr	plan = NULL;

	Oid		argtypes[] = {TEXTOID};
	Datum	values[1];
	char	nulls[1] = {' '};

	/* hack for availbility regress test */
	if (strcmp(path, "/tmp/regress_orafce") == 0)
		return;

	values[0] = CStringGetTextDatum(path);

	/*
	 * SELECT 1 FROM utl_file.utl_file_dir
	 *   WHERE substring($1, 1, length(dir) + 1) = dir || '/'
	 */

	if (SPI_connect() < 0)
		ereport(ERROR,
			(errcode(ERRCODE_INTERNAL_ERROR),
			 errmsg("SPI_connect failed")));

	if (!plan)
	{
		/* Don't use LIKE not to escape '_' and '%' */
		SPIPlanPtr p = SPI_prepare(
		    "SELECT 1 FROM utl_file.utl_file_dir"
			" WHERE substring($1, 1, length(dir) + 1) = dir || '/'",
		    1, argtypes);

		if (p == NULL || (plan = SPI_saveplan(p)) == NULL)
			ereport(ERROR,
				(errcode(ERRCODE_INTERNAL_ERROR),
				errmsg("SPI_prepare_failed")));
	}

	if (SPI_OK_SELECT != SPI_execute_plan(plan, values, nulls, false, 1))
		ereport(ERROR,
			(errcode(ERRCODE_INTERNAL_ERROR),
			 errmsg("can't execute sql")));

	if (SPI_processed == 0)
		ereport(ERROR,
			(errcode(ERRCODE_RAISE_EXCEPTION),
			 errmsg(INVALID_PATH),
			 errdetail("you cannot access locality"),
			 errhint("locality is not found in utl_file_dir table")));
	SPI_finish();
}
Example #7
0
/*
 * spi_exec_query
 *   Execute given SQL command via SPI.
 *   The plan will be cached by SPI_prepare if it hasn't been.
 */
static void
spi_exec_query(const char *query, int nargs, Oid *argtypes, SPIPlanPtr *plan,
				Datum *values, const char *nulls, int result)
{
	int	ret;

	if (*plan == NULL)
		*plan = SPI_prepare(query, nargs, argtypes);

	ret = SPI_execute_plan(*plan, values, nulls, false, 0);
	if (ret != result)
		elog(ERROR, "pg_dbms_stats: SPI_execute_plan => %d", ret);
}
Example #8
0
static int luaP_executeplan (lua_State *L) {
  luaP_Plan *p = (luaP_Plan *) luaP_checkudata(L, 1, PLLUA_PLANMT);
  bool ro = (bool) lua_toboolean(L, 3);
  long c = luaL_optlong(L, 4, 0);
  int result = -1;
  if (p->nargs > 0) {
    luaP_Buffer *b;
    if (lua_type(L, 2) != LUA_TTABLE) luaP_typeerror(L, 2, "table");
    b = luaP_getbuffer(L, p->nargs);
    luaP_fillbuffer(L, 2, p->type, b);
    luaP_TRY {
      result = SPI_execute_plan(p->plan, b->value, b->null, ro, c); 
    } luaP_CATCH;
  }
Example #9
0
int
SPI_execute_with_args(const char *src,
					  int nargs, Oid *argtypes,
					  Datum *values, const char *nulls,
					  bool read_only, long tcount)
{
	SPIPlanPtr	plan;
	int			ret;

	plan = SPI_prepare(src, nargs, argtypes);
	if (plan == NULL)
		return SPI_result;
	ret = SPI_execute_plan(plan, values, nulls, read_only, tcount);
	SPI_freeplan(plan);
	return ret;
}
Example #10
0
/*
 * Fill table information in hash table.
 */
static void fill_tbl_info(Relation rel, struct PgqTableInfo *info)
{
	StringInfo pkeys;
	Datum values[1];
	const char *name = find_table_name(rel);
	TupleDesc desc;
	HeapTuple row;
	bool isnull;
	int res, i, attno;

	/* allow reset ASAP, but ignore it in this call */
	info->invalid = false;

	/* load pkeys */
	values[0] = ObjectIdGetDatum(rel->rd_id);
	res = SPI_execute_plan(pkey_plan, values, NULL, false, 0);
	if (res != SPI_OK_SELECT)
		elog(ERROR, "pkey_plan exec failed");

	/*
	 * Fill info
	 */

	desc = SPI_tuptable->tupdesc;
	pkeys = makeStringInfo();
	info->n_pkeys = SPI_processed;
	info->table_name = MemoryContextStrdup(tbl_cache_ctx, name);
	info->pkey_attno = MemoryContextAlloc(tbl_cache_ctx, info->n_pkeys * sizeof(int));

	for (i = 0; i < SPI_processed; i++) {
		row = SPI_tuptable->vals[i];

		attno = DatumGetInt16(SPI_getbinval(row, desc, 1, &isnull));
		name = SPI_getvalue(row, desc, 2);
		info->pkey_attno[i] = attno;
		if (i > 0)
			appendStringInfoChar(pkeys, ',');
		appendStringInfoString(pkeys, name);
	}
	info->pkey_list = MemoryContextStrdup(tbl_cache_ctx, pkeys->data);
	info->tg_cache = NULL;
}
Example #11
0
/**
 * Create and run the basic query on the floatvalue table, for use by the wciReadFloat function
 */
static void runWciReadFloatQueryFloat(struct ReadStore * out, FunctionCallInfo fcinfo)
{
	struct WciReadParameterCollection p;
	parseReadParameters(& p, fcinfo);

	// This must match exactly the return type for wci.returnfloat
	const char * whatToSelect = "value::float, dataprovidername, placename::text, st_astext(placegeometry), referencetime, validtimefrom, validtimeto, validtimeindeterminatecode, valueparametername, valueunitname, levelparametername, levelunitname, levelfrom, levelto, levelindeterminatecode, dataversion, confidencecode, valuestoretime, valueid, valuetype";
	const char * gridQuery = build_query(& p, FloatTable, OutputFloat, whatToSelect, NULL);
	elog(DEBUG1, gridQuery);

	// Perform primary query
	SPIPlanPtr queryPlan = getSpiPlan(gridQuery);
	if (SPI_OK_SELECT != SPI_execute_plan(queryPlan, NULL, NULL, true, 0))
	{
		ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), errmsg(
				"Error when performing base query")));
	}

	out->tuples = SPI_tuptable;
	out->tupleCount = SPI_processed;
}
Example #12
0
static Oid
GetRelOid(Oid filenode)
{
	int			ret;
	Oid			relid;
	bool		isnull;
	Datum		value[1] = { ObjectIdGetDatum(filenode) };

	static SPIPlanPtr	plan = NULL;

	/* If this is our first time here, create a plan and save it for later calls. */
	if (plan == NULL)
	{
		StringInfoData	buf;
		Oid	paramType[1] = {OIDOID};

		initStringInfo(&buf);
		appendStringInfo(&buf, "select oid from pg_class where pg_relation_filenode(oid) = $1");

		plan = SPI_prepare(buf.data, 1, (Oid*)&paramType);

		if (plan == NULL)
			elog(ERROR, "SPI_prepare returned %d", SPI_result);
	}

	ret = SPI_execute_plan(plan, (Datum*)&value, NULL, true, 1);

	if (ret != SPI_OK_SELECT)
		ereport(FATAL, (errmsg("SPI_execute_plan failed: error code %d", ret)));

	if (SPI_processed < 1)
		return InvalidOid;

	relid = DatumGetObjectId(SPI_getbinval(SPI_tuptable->vals[0],
											SPI_tuptable->tupdesc, 1, &isnull));
	if (isnull)
		return InvalidOid;

	return relid;
}
Example #13
0
/*
 * Execute ProxyQuery locally.
 *
 * Result will be in SPI_tuptable.
 */
void
plproxy_query_exec(ProxyFunction *func, FunctionCallInfo fcinfo, ProxyQuery *q,
				   DatumArray **array_params, int array_row)
{
	int			i,
				idx,
				err;
	char		arg_nulls[FUNC_MAX_ARGS];
	Datum		arg_values[FUNC_MAX_ARGS];

	/* fill args */
	for (i = 0; i < q->arg_count; i++)
	{
		idx = q->arg_lookup[i];

		if (PG_ARGISNULL(idx))
		{
			arg_nulls[i] = 'n';
			arg_values[i] = (Datum) NULL;
		}
		else if (array_params && IS_SPLIT_ARG(func, idx))
		{
			DatumArray *ats = array_params[idx];

			arg_nulls[i] = ats->nulls[array_row] ? 'n' : ' ';
			arg_values[i] = ats->nulls[array_row] ? (Datum) NULL : ats->values[array_row];
		}
		else
		{
			arg_nulls[i] = ' ';
			arg_values[i] = PG_GETARG_DATUM(idx);
		}
	}

	/* run query */
	err = SPI_execute_plan(q->plan, arg_values, arg_nulls, true, 0);
	if (err != SPI_OK_SELECT)
		plproxy_error(func, "query '%s' failed: %s",
					  q->sql, SPI_result_code_string(err));
}
Example #14
0
static int
get_nnode(PlxFn *plx_fn, FunctionCallInfo fcinfo)
{
    PlxQuery   *plx_q = plx_fn->hash_query;
    int         err;
    SPIPlanPtr  plan;
    Oid         types[FUNC_MAX_ARGS];
    Datum       values[FUNC_MAX_ARGS];
    char        arg_nulls[FUNC_MAX_ARGS];
    Datum       val;
    bool        isnull;
    int         i;

    if ((err = SPI_connect()) != SPI_OK_CONNECT)
        plx_error(plx_fn, "SPI_connect: %s", SPI_result_code_string(err));

    for (i = 0; i < plx_q->nargs; i++)
    {
        int idx = plx_q->plx_fn_arg_indexes[i];

        types[i] = plx_fn->arg_types[idx]->oid;
        values[i] = PG_GETARG_DATUM(idx);
    }
    plan = SPI_prepare(plx_q->sql->data, plx_q->nargs, types);
    err = SPI_execute_plan(plan, values, arg_nulls, true, 0);
    if (err != SPI_OK_SELECT)
        plx_error(plx_fn,
                  "query '%s' failed: %s",
                  plx_q->sql->data,
                  SPI_result_code_string(err));
    val = SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, &isnull);
    err = SPI_finish();
    if (err != SPI_OK_FINISH)
        plx_error(plx_fn, "SPI_finish: %s", SPI_result_code_string(err));

    return DatumGetInt32(val);
}
Example #15
0
Datum
dbms_alert_defered_signal(PG_FUNCTION_ARGS)
{
	TriggerData *trigdata = (TriggerData *) fcinfo->context;
	TupleDesc tupdesc;
	HeapTuple rettuple;
	char *relname;
	text *name;
	text *message;
	int event_col;
	int message_col;

	Datum datum;
	bool isnull;
	int cycle = 0;
	float8 endtime;
	float8 timeout = 2;

	if (!CALLED_AS_TRIGGER(fcinfo))
		ereport(ERROR,
			(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
			 errmsg("not called by trigger manager")));

	if (!TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
		ereport(ERROR,
			(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
			 errmsg("not called on valid event")));

	if (SPI_connect() < 0)
		ereport(ERROR,
			(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
			 errmsg("SPI_connect failed")));

	if (strcmp((relname = SPI_getrelname(trigdata->tg_relation)), "ora_alerts") != 0)
		ereport(ERROR,
			(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
			 errmsg("not called with valid relation")));

	rettuple = trigdata->tg_trigtuple;
	tupdesc = trigdata->tg_relation->rd_att;

	if (SPI_ERROR_NOATTRIBUTE == (event_col = SPI_fnumber(tupdesc, "event")))
		ereport(ERROR,
			(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
			 errmsg("attribute event not found")));


	if (SPI_ERROR_NOATTRIBUTE == (message_col = SPI_fnumber(tupdesc, "message")))
		ereport(ERROR,
			(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
			 errmsg("attribute message not found")));

	datum = SPI_getbinval(rettuple, tupdesc, event_col, &isnull);
	if (isnull)
		ereport(ERROR,
    			(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
        		 errmsg("event name is NULL"),
			 errdetail("Eventname may not be NULL.")));
	name = DatumGetTextP(datum);

	datum = SPI_getbinval(rettuple, tupdesc, message_col, &isnull);
	if (isnull)
		message = NULL;
	else
		message = DatumGetTextP(datum);

	WATCH_PRE(timeout, endtime, cycle);
	if (ora_lock_shmem(SHMEMMSGSZ, MAX_PIPES, MAX_EVENTS, MAX_LOCKS, false))
	{
		ItemPointer tid;
		Oid argtypes[1] = {TIDOID};
		char nulls[1] = {' '};
		Datum values[1];
		void *plan;

		create_message(name, message);
		LWLockRelease(shmem_lock);

		tid = &rettuple->t_data->t_ctid;

		if (!(plan = SPI_prepare("DELETE FROM ora_alerts WHERE ctid = $1", 1, argtypes)))
			ereport(ERROR,
				(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
				 errmsg("SPI_prepare failed")));

		values[0] = ItemPointerGetDatum(tid);

		if (SPI_OK_DELETE != SPI_execute_plan(plan, values, nulls, false, 1))
			ereport(ERROR,
				(errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION),
				errmsg("can't execute sql")));

		SPI_finish();
		return PointerGetDatum(rettuple);
	}
	WATCH_POST(timeout, endtime, cycle);
	LOCK_ERROR();

	PG_RETURN_NULL();
}
Example #16
0
static PyObject *
PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
{
	volatile int nargs;
	int			i,
				rv;
	PLyPlanObject *plan;
	volatile MemoryContext oldcontext;
	volatile ResourceOwner oldowner;
	PyObject   *ret;

	if (list != NULL)
	{
		if (!PySequence_Check(list) || PyString_Check(list) || PyUnicode_Check(list))
		{
			PLy_exception_set(PyExc_TypeError, "plpy.execute takes a sequence as its second argument");
			return NULL;
		}
		nargs = PySequence_Length(list);
	}
	else
		nargs = 0;

	plan = (PLyPlanObject *) ob;

	if (nargs != plan->nargs)
	{
		char	   *sv;
		PyObject   *so = PyObject_Str(list);

		if (!so)
			PLy_elog(ERROR, "could not execute plan");
		sv = PyString_AsString(so);
		PLy_exception_set_plural(PyExc_TypeError,
							  "Expected sequence of %d argument, got %d: %s",
							 "Expected sequence of %d arguments, got %d: %s",
								 plan->nargs,
								 plan->nargs, nargs, sv);
		Py_DECREF(so);

		return NULL;
	}

	oldcontext = CurrentMemoryContext;
	oldowner = CurrentResourceOwner;

	PLy_spi_subtransaction_begin(oldcontext, oldowner);

	PG_TRY();
	{
		char	   *volatile nulls;
		volatile int j;

		if (nargs > 0)
			nulls = palloc(nargs * sizeof(char));
		else
			nulls = NULL;

		for (j = 0; j < nargs; j++)
		{
			PyObject   *elem;

			elem = PySequence_GetItem(list, j);
			if (elem != Py_None)
			{
				PG_TRY();
				{
					plan->values[j] =
						plan->args[j].out.d.func(&(plan->args[j].out.d),
												 -1,
												 elem);
				}
				PG_CATCH();
				{
					Py_DECREF(elem);
					PG_RE_THROW();
				}
				PG_END_TRY();

				Py_DECREF(elem);
				nulls[j] = ' ';
			}
			else
			{
				Py_DECREF(elem);
				plan->values[j] =
					InputFunctionCall(&(plan->args[j].out.d.typfunc),
									  NULL,
									  plan->args[j].out.d.typioparam,
									  -1);
				nulls[j] = 'n';
			}
		}

		rv = SPI_execute_plan(plan->plan, plan->values, nulls,
							  PLy_curr_procedure->fn_readonly, limit);
		ret = PLy_spi_execute_fetch_result(SPI_tuptable, SPI_processed, rv);

		if (nargs > 0)
			pfree(nulls);

		PLy_spi_subtransaction_commit(oldcontext, oldowner);
	}
	PG_CATCH();
	{
		int			k;

		/*
		 * cleanup plan->values array
		 */
		for (k = 0; k < nargs; k++)
		{
			if (!plan->args[k].out.d.typbyval &&
				(plan->values[k] != PointerGetDatum(NULL)))
			{
				pfree(DatumGetPointer(plan->values[k]));
				plan->values[k] = PointerGetDatum(NULL);
			}
		}

		PLy_spi_subtransaction_abort(oldcontext, oldowner);
		return NULL;
	}
	PG_END_TRY();

	for (i = 0; i < nargs; i++)
	{
		if (!plan->args[i].out.d.typbyval &&
			(plan->values[i] != PointerGetDatum(NULL)))
		{
			pfree(DatumGetPointer(plan->values[i]));
			plan->values[i] = PointerGetDatum(NULL);
		}
	}

	if (rv < 0)
	{
		PLy_exception_set(PLy_exc_spi_error,
						  "SPI_execute_plan failed: %s",
						  SPI_result_code_string(rv));
		return NULL;
	}

	return ret;
}
Example #17
0
File: payment.c Project: mw2q/dbt2
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 *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;

	Datum	args[8];
	char	nulls[8] = { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' };

	elog(DEBUG1, "w_id = %d", w_id);
	elog(DEBUG1, "d_id = %d", d_id);
	elog(DEBUG1, "c_id = %d", c_id);
	elog(DEBUG1, "c_w_id = %d", c_w_id);
	elog(DEBUG1, "c_d_id = %d", c_d_id);
	elog(DEBUG1, "c_last = %s",
			DatumGetCString(DirectFunctionCall1(textout,
			PointerGetDatum(c_last))));
	elog(DEBUG1, "h_amount = %f", h_amount);

	SPI_connect();

	plan_queries(statements);

	args[0] = Int32GetDatum(w_id);
	ret = SPI_execute_plan(PAYMENT_1, args, nulls, true, 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);
		elog(DEBUG1, "w_name = %s", w_name);
		elog(DEBUG1, "w_street_1 = %s", w_street_1);
		elog(DEBUG1, "w_street_2 = %s", w_street_2);
		elog(DEBUG1, "w_city = %s", w_city);
		elog(DEBUG1, "w_state = %s", w_state);
		elog(DEBUG1, "w_zip = %s", w_zip);
	} else {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	args[0] = Float4GetDatum(h_amount);
	args[1] = Int32GetDatum(w_id);
	ret = SPI_execute_plan(PAYMENT_2, args, nulls, false, 0);
	if (ret != SPI_OK_UPDATE) {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	args[0] = Int32GetDatum(d_id);
	args[1] = Int32GetDatum(w_id);
	ret = SPI_execute_plan(PAYMENT_3, args, nulls, true, 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);
		elog(DEBUG1, "d_name = %s", d_name);
		elog(DEBUG1, "d_street_1 = %s", d_street_1);
		elog(DEBUG1, "d_street_2 = %s", d_street_2);
		elog(DEBUG1, "d_city = %s", d_city);
		elog(DEBUG1, "d_state = %s", d_state);
		elog(DEBUG1, "d_zip = %s", d_zip);
	} else {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	args[0] = Float4GetDatum(h_amount);
	args[1] = Int32GetDatum(d_id);
	args[2] = Int32GetDatum(w_id);
	ret = SPI_execute_plan(PAYMENT_4, args, nulls, false, 0);
	if (ret != SPI_OK_UPDATE) {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	if (c_id == 0) {
		args[0] = Int32GetDatum(w_id);
		args[1] = Int32GetDatum(d_id);
		args[2] = PointerGetDatum(c_last);
		ret = SPI_execute_plan(PAYMENT_5, args, nulls, true, 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);
			elog(DEBUG1, "c_id = %s, %d total, selected %d",
					tmp_c_id, count, count / 2);
			my_c_id = atoi(tmp_c_id);
		} else {
			SPI_finish();
			PG_RETURN_INT32(-1);
		}
	} else {
		my_c_id = c_id;
	}

	args[0] = Int32GetDatum(c_w_id);
	args[1] = Int32GetDatum(c_d_id);
	args[2] = Int32GetDatum(my_c_id);
	ret = SPI_execute_plan(PAYMENT_6, args, nulls, true, 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);
		elog(DEBUG1, "c_first = %s", c_first);
		elog(DEBUG1, "c_middle = %s", c_middle);
		elog(DEBUG1, "c_last = %s", my_c_last);
		elog(DEBUG1, "c_street_1 = %s", c_street_1);
		elog(DEBUG1, "c_street_2 = %s", c_street_2);
		elog(DEBUG1, "c_city = %s", c_city);
		elog(DEBUG1, "c_state = %s", c_state);
		elog(DEBUG1, "c_zip = %s", c_zip);
		elog(DEBUG1, "c_phone = %s", c_phone);
		elog(DEBUG1, "c_since = %s", c_since);
		elog(DEBUG1, "c_credit = %s", c_credit);
		elog(DEBUG1, "c_credit_lim = %s", c_credit_lim);
		elog(DEBUG1, "c_discount = %s", c_discount);
		elog(DEBUG1, "c_balance = %s", c_balance);
		elog(DEBUG1, "c_data = %s", c_data);
		elog(DEBUG1, "c_ytd_payment = %s", c_ytd_payment);
	} else {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	/* It's either "BC" or "GC". */
	if (c_credit[0] == 'G') {
		args[0] = Float4GetDatum(h_amount);
		args[1] = Int32GetDatum(my_c_id);
		args[2] = Int32GetDatum(c_w_id);
		args[3] = Int32GetDatum(c_d_id);
		ret = SPI_execute_plan(PAYMENT_7_GC, args, nulls, false, 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);

		args[0] = Float4GetDatum(h_amount);
		args[1] = CStringGetTextDatum(my_c_data);
		args[2] = Int32GetDatum(my_c_id);
		args[3] = Int32GetDatum(c_w_id);
		args[4] = Int32GetDatum(c_d_id);
		ret = SPI_execute_plan(PAYMENT_7_BC, args, nulls, false, 0);
		if (ret != SPI_OK_UPDATE) {
			SPI_finish();
			PG_RETURN_INT32(-1);
		}
	}

	args[0] = Int32GetDatum(my_c_id);
	args[1] = Int32GetDatum(c_d_id);
	args[2] = Int32GetDatum(c_w_id);
	args[3] = Int32GetDatum(d_id);
	args[4] = Int32GetDatum(w_id);
	args[5] = Float4GetDatum(h_amount);
	args[6] = CStringGetTextDatum(w_name);
	args[7] = CStringGetTextDatum(d_name);
	ret = SPI_execute_plan(PAYMENT_8, args, nulls, false, 0);
	if (ret != SPI_OK_INSERT) {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	SPI_finish();
	PG_RETURN_INT32(1);
}
Example #18
0
static int
load_rows(PyObj self, PyObj row_iter, uint32 *total)
{
	MemoryContext former = CurrentMemoryContext;
	volatile PyObj row = NULL;
	Datum *datums;
	bool *nulls;
	char *cnulls;
	int r = 0;
	SPIPlanPtr plan;

	Assert(!ext_state);
	Assert(PyIter_Check(row_iter));

	plan = PyPgStatement_GetPlan(self);
	if (plan == NULL)
		return(-1);

	PG_TRY();
	{
		PyObj tdo = PyPgStatement_GetInput(self);
		PyObj typs = PyPgTupleDesc_GetTypesTuple(tdo);
		PyObj namemap = PyPgTupleDesc_GetNameMap(tdo);
		TupleDesc td = PyPgTupleDesc_GetTupleDesc(tdo);
		int rnatts = PyPgTupleDesc_GetNatts(tdo);
		int *freemap = PyPgTupleDesc_GetFreeMap(tdo);
		int spi_r;

		datums = palloc(sizeof(Datum) * td->natts);
		nulls = palloc(sizeof(bool) * td->natts);
		cnulls = palloc(sizeof(char) * td->natts);

		while ((row = PyIter_Next(row_iter)))
		{
			PyObj pargs;
			pargs = Py_NormalizeRow(rnatts, td, namemap, row);
			Py_DECREF(row);
			if (pargs == NULL)
			{
				r = -1;
				break;
			}
			row = pargs;

			Py_BuildDatumsAndNulls(td, typs, row, datums, nulls);

			Py_DECREF(row);
			row = NULL;

			/* borrow spi_r for a moment */
			for (spi_r = 0; spi_r < td->natts; ++spi_r)
			{
				cnulls[spi_r] = nulls[spi_r] ? 'n' : ' ';
			}
			spi_r = SPI_execute_plan(plan, datums, cnulls, false, 1);

			/*
			 * Free the built datums.
			 */
			FreeReferences(freemap, datums, nulls);

			if (spi_r < 0)
				raise_spi_error(spi_r);

			*total = *total + SPI_processed;
		}

		pfree(datums);
		pfree(nulls);
		pfree(cnulls);
	}
	PG_CATCH();
	{
		/*
		 * WARNING: Leaks datums & nulls on error. Yay, procCxt.
		 */
		PyErr_SetPgError(false);
		Py_XDECREF(row);
		r = -1;
	}
	PG_END_TRY();
	MemoryContextSwitchTo(former);

	return(r);
}
Example #19
0
/* Clause 3.3.9.3 */
Datum TradeUpdateFrame1(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	AttInMetadata *attinmeta;
	int call_cntr;
	int max_calls;

	int i;
	int j;

	char **values = NULL;

	/* Stuff done only on the first call of the function. */
	if (SRF_IS_FIRSTCALL()) {
		MemoryContext oldcontext;

		enum tuf1 {
				i_bid_price=0, i_cash_transaction_amount,
				i_cash_transaction_dts, i_cash_transaction_name, i_exec_name,
				i_is_cash, i_is_market, i_num_found, i_num_updated,
				i_settlement_amount, i_settlement_cash_due_date,
				i_settlement_cash_type, i_trade_history_dts,
				i_trade_history_status_id, i_trade_price
		};

		int max_trades = PG_GETARG_INT32(0);
		int max_updates = PG_GETARG_INT32(1);
		ArrayType *trade_id_p = PG_GETARG_ARRAYTYPE_P(2);

		int16 typlen;
		bool typbyval;
		char typalign;

		int ndim, nitems;
		int *dim;
		long *trade_id;

		int ret;
		TupleDesc tupdesc;
		SPITupleTable *tuptable = NULL;
		HeapTuple tuple = NULL;
#ifdef DEBUG
		char sql[2048];
#endif
		Datum args[2];
		char nulls[2] = { ' ', ' ' };

		int num_found = max_trades;
		int num_updated = 0;
		int num_updated4 = 0;
		int num_updated5 = 0;
		int num_updated7 = 0;
		int num_cash = 0;

		ndim = ARR_NDIM(trade_id_p);
		dim = ARR_DIMS(trade_id_p);
		nitems = ArrayGetNItems(ndim, dim);

		get_typlenbyvalalign(ARR_ELEMTYPE(trade_id_p), &typlen, &typbyval,
				&typalign);
		trade_id = (long *) ARR_DATA_PTR(trade_id_p);

		/*
		 * Prepare a values array for building the returned tuple.
		 * This should be an array of C strings, which will
		 * be processed later by the type input functions.
		 * Don't forget to factor in commas (,) and braces ({}) for the arrays.
		 */
		values = (char **) palloc(sizeof(char *) * 15);
		values[i_bid_price] =
				(char *) palloc(((S_PRICE_T_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_cash_transaction_amount] =
				(char *) palloc(((VALUE_T_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_cash_transaction_dts] =
				(char *) palloc(((MAXDATELEN + 1) * 20 + 2) * sizeof(char));
		values[i_cash_transaction_name] =
				(char *) palloc(((CT_NAME_LEN + 3) * 20 + 2) * sizeof(char));
		values[i_exec_name] = (char *) palloc(((T_EXEC_NAME_LEN + 3) * 20 +
				2) * sizeof(char));
		values[i_is_cash] =
				(char *) palloc(((SMALLINT_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_is_market] =
				(char *) palloc(((SMALLINT_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_num_found] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
		values[i_num_updated] =
				(char *) palloc((INTEGER_LEN + 1) * sizeof(char));
		values[i_settlement_amount] =
				(char *) palloc(((VALUE_T_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_settlement_cash_due_date] =
				(char *) palloc(((MAXDATELEN + 1) * 20 + 2) * sizeof(char));
		values[i_settlement_cash_type] = (char *) palloc(((SE_CASH_TYPE_LEN +
				3) * 20 + 2) * sizeof(char));
		values[i_trade_history_dts] = (char *) palloc(((MAXDATELEN * 3 + 4) *
				20 + 22) * sizeof(char));
		values[i_trade_history_status_id] = (char *) palloc((((ST_ID_LEN +
				2) * 3 + 4) * 20 + 22) * sizeof(char));
		values[i_trade_price] =
				(char *) palloc(((S_PRICE_T_LEN + 1) * 20 + 2) * sizeof(char));

#ifdef DEBUG
		dump_tuf1_inputs(max_trades, max_updates, trade_id);
#endif

		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();
		funcctx->max_calls = 1;

		/* switch to memory context appropriate for multiple function calls */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		SPI_connect();
		plan_queries(TUF1_statements);

		strcpy(values[i_bid_price], "{");
		strcpy(values[i_exec_name], "{");
		strcpy(values[i_is_cash], "{");
		strcpy(values[i_is_market], "{");
		strcpy(values[i_trade_price], "{");
		strcpy(values[i_settlement_amount], "{");
		strcpy(values[i_settlement_cash_due_date], "{");
		strcpy(values[i_settlement_cash_type], "{");
		strcpy(values[i_cash_transaction_amount], "{");
		strcpy(values[i_cash_transaction_dts], "{");
		strcpy(values[i_cash_transaction_name], "{");
		strcpy(values[i_trade_history_dts], "{");
		strcpy(values[i_trade_history_status_id], "{");
		for (i = 0; i < max_trades; i++) {
			char *is_cash_str = NULL;
			char *is_market_str;

			if (num_updated < max_updates) {
				char *ex_name;

#ifdef DEBUG
				sprintf(sql, SQLTUF1_1, trade_id[i]);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[0] = Int64GetDatum(trade_id[i]);
				ret = SPI_execute_plan(TUF1_1, args, nulls, true, 0);
				if (ret == SPI_OK_SELECT && SPI_processed > 0) {
					tupdesc = SPI_tuptable->tupdesc;
					tuptable = SPI_tuptable;
					tuple = tuptable->vals[0];
					ex_name = SPI_getvalue(tuple, tupdesc, 1);
				} else {
					continue;
				}

#ifdef DEBUG
				elog(NOTICE, "ex_name = %s", ex_name);

				if (strstr(ex_name, " X ")) {
					sprintf(sql, SQLTUF1_2a, ex_name);
				} else {
					sprintf(sql, SQLTUF1_2b, ex_name);
				}
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[0] = CStringGetTextDatum(ex_name);
				if (strstr(ex_name, " X ")) {
					ret = SPI_execute_plan(TUF1_2a,
							args, nulls, true, 0);
				} else {
					ret = SPI_execute_plan(TUF1_2b,
							args, nulls, true, 0);
				}
				if (ret == SPI_OK_SELECT && SPI_processed > 0) {
					tupdesc = SPI_tuptable->tupdesc;
					tuptable = SPI_tuptable;
					tuple = tuptable->vals[0];
					ex_name = SPI_getvalue(tuple, tupdesc, 1);
				} else {
					FAIL_FRAME_SET(&funcctx->max_calls,
					strstr(ex_name, " X ")? TUF1_statements[1].sql:
								TUF1_statements[2].sql);
					dump_tuf1_inputs(max_trades, max_updates, trade_id);
					continue;
				}

#ifdef DEBUG
				elog(NOTICE, "ex_name = %s", ex_name);
				sprintf(sql, SQLTUF1_3, ex_name, trade_id[i]);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[1] = Int64GetDatum(trade_id[i]);
				ret = SPI_execute_plan(TUF1_3, args, nulls, false, 0);
				if (ret != SPI_OK_UPDATE) {
					FAIL_FRAME_SET(&funcctx->max_calls,
								TUF1_statements[4].sql);
					dump_tuf1_inputs(max_trades, max_updates, trade_id);
					continue;
				}

				num_updated += SPI_processed;
			}

#ifdef DEBUG
			sprintf(sql, SQLTUF1_4, trade_id[i]);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			args[0] = Int64GetDatum(trade_id[i]);
			ret = SPI_execute_plan(TUF1_4, args, nulls, true, 0);
			if (ret != SPI_OK_SELECT) {
				FAIL_FRAME_SET(&funcctx->max_calls,
							TUF1_statements[5].sql);
				dump_tuf1_inputs(max_trades, max_updates, trade_id);
				continue;
			}

			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
			for (j = 0; j < SPI_processed; j++) {
				char *trade_price;
				if (num_updated4 > 0) {
					strcat(values[i_bid_price], ",");
					strcat(values[i_exec_name], ",");
					strcat(values[i_is_cash], ",");
					strcat(values[i_is_market], ",");
					strcat(values[i_trade_price], ",");
				}

				tuple = tuptable->vals[j];
				strcat(values[i_bid_price], SPI_getvalue(tuple, tupdesc, 1));
				strcat(values[i_exec_name], "\"");
				strcat(values[i_exec_name], SPI_getvalue(tuple, tupdesc, 2));
				strcat(values[i_exec_name], "\"");
				is_cash_str = SPI_getvalue(tuple, tupdesc, 3);
				strcat(values[i_is_cash], (is_cash_str[0] == 't' ? "1": "0"));
				is_market_str = SPI_getvalue(tuple, tupdesc, 4);
				strcat(values[i_is_market],
						(is_market_str[0] == 't' ? "0" : "1"));
				trade_price = SPI_getvalue(tuple, tupdesc, 5);
				if (trade_price != NULL)
					strcat(values[i_trade_price],
							SPI_getvalue(tuple, tupdesc, 5));
				else
					strcat(values[i_trade_price], "NULL");

				num_updated4++;
			}

#ifdef DEBUG
			sprintf(sql, SQLTUF1_5, trade_id[i]);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			ret = SPI_execute_plan(TUF1_5, args, nulls, true, 0);
			if (ret != SPI_OK_SELECT) {
				FAIL_FRAME_SET(&funcctx->max_calls,
							TUF1_statements[6].sql);
				dump_tuf1_inputs(max_trades, max_updates, trade_id);
				continue;
			}

			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
			for (j = 0; j < SPI_processed; j++) {
				if (num_updated5 > 0) {
					strcat(values[i_settlement_amount], ",");
					strcat(values[i_settlement_cash_due_date], ",");
					strcat(values[i_settlement_cash_type], ",");
				}

				tuple = tuptable->vals[j];
				strcat(values[i_settlement_amount],
						SPI_getvalue(tuple, tupdesc, 1));
				strcat(values[i_settlement_cash_due_date],
						SPI_getvalue(tuple, tupdesc, 2));
				strcat(values[i_settlement_cash_type], "\"");
				strcat(values[i_settlement_cash_type],
						SPI_getvalue(tuple, tupdesc, 3));
				strcat(values[i_settlement_cash_type], "\"");

				num_updated5++;
			}

			if (is_cash_str[0] == 't') {
				if (num_cash > 0) {
					strcat(values[i_cash_transaction_amount], ",");
					strcat(values[i_cash_transaction_dts], ",");
					strcat(values[i_cash_transaction_name], ",");
				}

#ifdef DEBUG
				sprintf(sql, SQLTUF1_6, trade_id[i]);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				ret = SPI_execute_plan(TUF1_6, args, nulls, true, 0);
				if (ret == SPI_OK_SELECT && SPI_processed > 0) {
					tupdesc = SPI_tuptable->tupdesc;
					tuptable = SPI_tuptable;
					tuple = tuptable->vals[0];
					strcat(values[i_cash_transaction_amount],
							SPI_getvalue(tuple, tupdesc, 1));
					strcat(values[i_cash_transaction_dts],
							SPI_getvalue(tuple, tupdesc, 2));
					strcat(values[i_cash_transaction_name], "\"");
					strcat(values[i_cash_transaction_name],
							SPI_getvalue(tuple, tupdesc, 3));
					strcat(values[i_cash_transaction_name], "\"");
					++num_cash;
				} else {
					FAIL_FRAME_SET(&funcctx->max_calls,
								TUF1_statements[7].sql);
					dump_tuf1_inputs(max_trades, max_updates, trade_id);
					continue;
				}
			}

#ifdef DEBUG
			sprintf(sql, SQLTUF1_7, trade_id[i]);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			ret = SPI_execute_plan(TUF1_7, args, nulls, true, 0);
			if (ret == SPI_OK_SELECT) {
				tupdesc = SPI_tuptable->tupdesc;
				tuptable = SPI_tuptable;
			} else {
				FAIL_FRAME_SET(&funcctx->max_calls,
							TUF1_statements[8].sql);
				dump_tuf1_inputs(max_trades, max_updates, trade_id);
				continue;
			}

			if (num_updated7 > 0) {
				strcat(values[i_trade_history_dts], ",");
				strcat(values[i_trade_history_status_id], ",");
			}
			strcat(values[i_trade_history_dts], "{");
			strcat(values[i_trade_history_status_id], "{");
			for (j = 0; j < SPI_processed; j++) {
				if (j > 0) {
					strcat(values[i_trade_history_dts], ",");
					strcat(values[i_trade_history_status_id], ",");
				}

				tuple = tuptable->vals[j];
				strcat(values[i_trade_history_dts],
							SPI_getvalue(tuple, tupdesc, 1));
				strcat(values[i_trade_history_status_id], "\"");
				strcat(values[i_trade_history_status_id],
							SPI_getvalue(tuple, tupdesc, 2));
				strcat(values[i_trade_history_status_id], "\"");

				num_updated7++;
			}
			for (j = SPI_processed; j < 3; j++) {
				if (j > 0) {
					strcat(values[i_trade_history_dts], ",");
					strcat(values[i_trade_history_status_id], ",");
				}
				strcat(values[i_trade_history_dts], "NULL");
				strcat(values[i_trade_history_status_id], "\"\"");

				num_updated7++;
			}
			strcat(values[i_trade_history_dts], "}");
			strcat(values[i_trade_history_status_id], "}");
		}
		strcat(values[i_bid_price], "}");
		strcat(values[i_exec_name], "}");
		strcat(values[i_is_cash], "}");
		strcat(values[i_is_market], "}");
		strcat(values[i_trade_price], "}");
		strcat(values[i_settlement_amount], "}");
		strcat(values[i_settlement_cash_due_date], "}");
		strcat(values[i_settlement_cash_type], "}");
		strcat(values[i_cash_transaction_amount], "}");
		strcat(values[i_cash_transaction_dts], "}");
		strcat(values[i_cash_transaction_name], "}");
		strcat(values[i_trade_history_dts], "}");
		strcat(values[i_trade_history_status_id], "}");

		sprintf(values[i_num_found], "%d", num_found);
		sprintf(values[i_num_updated], "%d", num_updated);

		/* 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")));
		}

		/*
		 * generate attribute metadata needed later to produce tuples from raw
		 * C strings
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	attinmeta = funcctx->attinmeta;

	if (call_cntr < max_calls) {
		/* do when there is more left to send */
		HeapTuple tuple;
		Datum result;

#ifdef DEBUG
		for (i = 0; i < 15; i++) {
			elog(NOTICE, "TUF1 OUT: %d %s", i, values[i]);
		}
#endif /* DEBUG */

		/* Build a tuple. */
		tuple = BuildTupleFromCStrings(attinmeta, values);

		/* Make the tuple into a datum. */
		result = HeapTupleGetDatum(tuple);

		SRF_RETURN_NEXT(funcctx, result);
	} else {
		/* Do when there is no more left. */
		SPI_finish();
		SRF_RETURN_DONE(funcctx);
	}
}
Example #20
0
/* Clause 3.3.1.3 */
Datum BrokerVolumeFrame1(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	AttInMetadata *attinmeta;
	int call_cntr;
	int max_calls;

	int i;

	int ndim, nitems;
	int *dim;
	char *broker_list;	

	char **values = NULL;

	/* Stuff done only on the first call of the function. */
	if (SRF_IS_FIRSTCALL()) {
		MemoryContext oldcontext;

		ArrayType *broker_list_p = PG_GETARG_ARRAYTYPE_P(0);
		text *sector_name_p = PG_GETARG_TEXT_P(1);

		enum bvf1 { i_broker_name=0, i_list_len, i_volume };

		int16 typlen;
		bool typbyval;
		char typalign;

		int ret;
		TupleDesc tupdesc;
		SPITupleTable *tuptable = NULL;
		HeapTuple tuple = NULL;
#ifdef DEBUG
		char sql[2048];
#endif
		char broker_list_array[(B_NAME_LEN + 3) * 40 + 5] = "'{";
		Datum args[2];
		char nulls[2] = { ' ', ' ' };

		/*
		 * Prepare a values array for building the returned tuple.
		 * This should be an array of C strings, which will
		 * be processed later by the type input functions.
		 */
		values = (char **) palloc(sizeof(char *) * 3);
		values[i_list_len] = (char *) palloc((SMALLINT_LEN + 1) * sizeof(char));

		/*
		 * This might be overkill since we always expect single dimensions
		 * arrays.
		 */
		ndim = ARR_NDIM(broker_list_p);
		dim = ARR_DIMS(broker_list_p);
		nitems = ArrayGetNItems(ndim, dim);
		get_typlenbyvalalign(ARR_ELEMTYPE(broker_list_p), &typlen, &typbyval,
				&typalign);
		broker_list = ARR_DATA_PTR(broker_list_p);
		/* Turn the broker_list input into an array format. */
		if (nitems > 0) {
			strcat(broker_list_array, "\"");
			strcat(broker_list_array,
					DatumGetCString(DirectFunctionCall1(textout,
					PointerGetDatum(broker_list))));
			broker_list = att_addlength_pointer(broker_list, typlen,
					broker_list);
			broker_list = (char *) att_align_nominal(broker_list,
					typalign);
			strcat(broker_list_array, "\"");
		}
		for (i = 1; i < nitems; i++) {
			strcat(broker_list_array, ",\"");
			strcat(broker_list_array,
					DatumGetCString(DirectFunctionCall1(textout,
					PointerGetDatum(broker_list))));
			broker_list = att_addlength_pointer(broker_list, typlen,
					broker_list);
			broker_list = (char *) att_align_nominal(broker_list,
					typalign);
			strcat(broker_list_array, "\"");
		}
		strcat(broker_list_array, "}'");
#ifdef DEBUG
		dump_bvf1_inputs(broker_list_p, sector_name_p);
#endif

		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();
		funcctx->max_calls = 1;

		/* switch to memory context appropriate for multiple function calls */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		SPI_connect();
		plan_queries(BVF1_statements);
#ifdef DEBUG
		sprintf(sql, SQLBVF1_1, broker_list_array,
				DatumGetCString(DirectFunctionCall1(textout,
				PointerGetDatum(sector_name_p))));
		elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
		args[0] = PointerGetDatum(broker_list_p);
		args[1] = PointerGetDatum(sector_name_p);
		ret = SPI_execute_plan(BVF1_1, args, nulls, true, 0);
		if (ret == SPI_OK_SELECT) {
			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
			tuple = tuptable->vals[0];
		} else {
			dump_bvf1_inputs(broker_list_p, sector_name_p);
			FAIL_FRAME_SET(&funcctx->max_calls, BVF1_statements[0].sql);
		}

		sprintf(values[i_list_len], "%d", SPI_processed);
		values[i_broker_name] = (char *) palloc(((B_NAME_LEN + 2) *
				(SPI_processed + 1) + 3) * sizeof(char));
		values[i_volume] = (char *) palloc((INTEGER_LEN *
				(SPI_processed + 1) + 3) * sizeof(char));

		if (SPI_processed == 0) {
			strcpy(values[i_broker_name], "{}");
			strcpy(values[i_volume], "{}");
		} else {
			strcpy(values[i_broker_name], "{");
			strcpy(values[i_volume], "{");

			if (SPI_processed > 0) {
				strcat(values[i_broker_name], "\"");
				strcat(values[i_broker_name], SPI_getvalue(tuple, tupdesc, 1));
				strcat(values[i_broker_name], "\"");
				strcat(values[i_volume], SPI_getvalue(tuple, tupdesc, 2));
			}
			for (i = 1; i < SPI_processed; i++) {
				tuple = tuptable->vals[i];
				strcat(values[i_broker_name], ",");
				strcat(values[i_broker_name], "\"");
				strcat(values[i_broker_name], SPI_getvalue(tuple, tupdesc, 1));
				strcat(values[i_broker_name], "\"");

				strcat(values[i_volume], ",");
				strcat(values[i_volume], SPI_getvalue(tuple, tupdesc, 2));
			}
			strcat(values[i_broker_name], "}");
			strcat(values[i_volume], "}");
		}

		/* 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")));
		}

		/*
		 * generate attribute metadata needed later to produce tuples from raw
		 * C strings
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	attinmeta = funcctx->attinmeta;

	if (call_cntr < max_calls) {
		/* do when there is more left to send */
		HeapTuple tuple;
		Datum result;

#ifdef DEBUG                                                                    
		for (i = 0; i < 3; i++) {
			elog(NOTICE, "BVF1 OUT: %d %s", i, values[i]);
		}
#endif /* DEBUG */

		/* Build a tuple. */
		tuple = BuildTupleFromCStrings(attinmeta, values);

		/* Make the tuple into a datum. */
		result = HeapTupleGetDatum(tuple);

		SRF_RETURN_NEXT(funcctx, result);
	} else {
		/* Do when there is no more left. */
		SPI_finish();
		SRF_RETURN_DONE(funcctx);
	}
}
Example #21
0
/* Clause 3.3.9.3 */
Datum TradeStatusFrame1(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	AttInMetadata *attinmeta;
	int call_cntr;
	int max_calls;

	int i;

	char **values = NULL;

	/* Stuff done only on the first call of the function. */
	if (SRF_IS_FIRSTCALL()) {
		enum tsf1 {
				i_broker_name=0, i_charge, i_cust_f_name, i_cust_l_name,
				i_ex_name, i_exec_name, i_num_found, i_s_name, i_status_name,
				i_symbol, i_trade_dts, i_trade_id, i_trade_qty, i_type_name
		};

		long acct_id = PG_GETARG_INT64(0);

		int ret;
		TupleDesc tupdesc;
		SPITupleTable *tuptable = NULL;
		HeapTuple tuple = NULL;
#ifdef DEBUG
		char sql[2048];
#endif
		Datum args[1];
		char nulls[1] = { ' ' };
		/*
		 * Prepare a values array for building the returned tuple.
		 * This should be an array of C strings, which will
		 * be processed later by the type input functions.
		 */
		values = (char **) palloc(sizeof(char *) * 14);
		values[i_charge] =
				(char *) palloc((VALUE_T_LEN + 1) * sizeof(char) * 50);
		values[i_ex_name] =
				(char *) palloc((EX_NAME_LEN + 3) * sizeof(char) * 50);
		values[i_exec_name] =
				(char *) palloc((T_EXEC_NAME_LEN + 3) * sizeof(char) * 50);
		values[i_num_found] = (char *) palloc((BIGINT_LEN + 1) * sizeof(char));
		values[i_s_name] =
				(char *) palloc((S_NAME_LEN + 3) * sizeof(char) * 50);
		values[i_status_name] =
				(char *) palloc((ST_NAME_LEN + 3) * sizeof(char) * 50);
		values[i_symbol] =
				(char *) palloc((S_SYMB_LEN + 3) * sizeof(char) * 50);
		values[i_trade_dts] =
				(char *) palloc((MAXDATELEN + 1) * sizeof(char) * 50);
		values[i_trade_id] =
				(char *) palloc((BIGINT_LEN + 1) * sizeof(char) * 50);
		values[i_trade_qty] =
				(char *) palloc((INTEGER_LEN + 1) * sizeof(char) * 50);
		values[i_type_name] =
				(char *) palloc((TT_NAME_LEN + 3) * sizeof(char) * 50);

		values[i_cust_l_name] = NULL;
		values[i_cust_f_name] = NULL;
		values[i_broker_name] = NULL;

#ifdef DEBUG
		dump_tsf1_inputs(acct_id);
#endif

		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();
		funcctx->max_calls = 1;

		/* switch to memory context appropriate for multiple function calls */
		TSF1_savedcxt = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		SPI_connect();
		plan_queries(TSF1_statements);
#ifdef DEBUG
		sprintf(sql, SQLTSF1_1, acct_id);
		elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
		args[0] = Int64GetDatum(acct_id);
		ret = SPI_execute_plan(TSF1_1, args, nulls, true, 0);
		if (ret == SPI_OK_SELECT) {
			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
		} else {
			FAIL_FRAME_SET(&funcctx->max_calls, TSF1_statements[0].sql);
			dump_tsf1_inputs(acct_id);
		}
		sprintf(values[i_num_found], "%d", SPI_processed);
		strcpy(values[i_trade_id], "{");
		strcpy(values[i_trade_dts], "{");
		strcpy(values[i_status_name], "{");
		strcpy(values[i_type_name], "{");
		strcpy(values[i_symbol], "{");
		strcpy(values[i_trade_qty], "{");
		strcpy(values[i_exec_name], "{");
		strcpy(values[i_charge], "{");
		strcpy(values[i_s_name], "{");
		strcpy(values[i_ex_name], "{");
		for (i = 0; i < SPI_processed; i++) {
			tuple = tuptable->vals[i];
			if (i > 0) {
				strcat(values[i_trade_id], ",");
				strcat(values[i_trade_dts], ",");
				strcat(values[i_status_name], ",");
				strcat(values[i_type_name], ",");
				strcat(values[i_symbol], ",");
				strcat(values[i_trade_qty], ",");
				strcat(values[i_exec_name], ",");
				strcat(values[i_charge], ",");
				strcat(values[i_s_name], ",");
				strcat(values[i_ex_name], ",");
			}
			strcat(values[i_trade_id], SPI_getvalue(tuple, tupdesc, 1));
			strcat(values[i_trade_dts], SPI_getvalue(tuple, tupdesc, 2));
			strcat(values[i_status_name], "\"");
			strcat(values[i_status_name], SPI_getvalue(tuple, tupdesc, 3));
			strcat(values[i_status_name], "\"");
			strcat(values[i_type_name], "\"");
			strcat(values[i_type_name], SPI_getvalue(tuple, tupdesc, 4));
			strcat(values[i_type_name], "\"");
			strcat(values[i_symbol], "\"");
			strcat(values[i_symbol], SPI_getvalue(tuple, tupdesc, 5));
			strcat(values[i_symbol], "\"");
			strcat(values[i_trade_qty], SPI_getvalue(tuple, tupdesc, 6));
			strcat(values[i_exec_name], "\"");
			strcat(values[i_exec_name], SPI_getvalue(tuple, tupdesc, 7));
			strcat(values[i_exec_name], "\"");
			strcat(values[i_charge], SPI_getvalue(tuple, tupdesc, 8));
			strcat(values[i_s_name], "\"");
			strcat(values[i_s_name], SPI_getvalue(tuple, tupdesc, 9));
			strcat(values[i_s_name], "\"");
			strcat(values[i_ex_name], "\"");
			strcat(values[i_ex_name], SPI_getvalue(tuple, tupdesc, 10));
			strcat(values[i_ex_name], "\"");
		}
		strcat(values[i_trade_id], "}");
		strcat(values[i_trade_dts], "}");
		strcat(values[i_status_name], "}");
		strcat(values[i_type_name], "}");
		strcat(values[i_symbol], "}");
		strcat(values[i_trade_qty], "}");
		strcat(values[i_exec_name], "}");
		strcat(values[i_charge], "}");
		strcat(values[i_s_name], "}");
		strcat(values[i_ex_name], "}");

#ifdef DEBUG
		sprintf(sql, SQLTSF1_2, acct_id);
		elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
		ret = SPI_execute_plan(TSF1_2, args, nulls, true, 0);
		if (ret == SPI_OK_SELECT) {
			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
			if (SPI_processed > 0) {
				tuple = tuptable->vals[0];
				values[i_cust_l_name] = SPI_getvalue(tuple, tupdesc, 1);
				values[i_cust_f_name] = SPI_getvalue(tuple, tupdesc, 2);
				values[i_broker_name] = SPI_getvalue(tuple, tupdesc, 3);
			}
		} else {
			FAIL_FRAME_SET(&funcctx->max_calls, TSF1_statements[1].sql);
			dump_tsf1_inputs(acct_id);
		}
		/* 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")));
		}

		/*
		 * generate attribute metadata needed later to produce tuples from raw
		 * C strings
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		MemoryContextSwitchTo(TSF1_savedcxt);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	attinmeta = funcctx->attinmeta;

	if (call_cntr < max_calls) {
		/* do when there is more left to send */
		HeapTuple tuple;
		Datum result;

#ifdef DEBUG
		for (i = 0; i < 14; i++) {
			elog(NOTICE, "TSF1 OUT: %d %s", i, values[i]);
		}
#endif /* DEBUG */

		/* Build a tuple. */
		tuple = BuildTupleFromCStrings(attinmeta, values);

		/* Make the tuple into a datum. */
		result = HeapTupleGetDatum(tuple);

		SRF_RETURN_NEXT(funcctx, result);
	} else {
		/* Do when there is no more left. */
		SPI_finish();
		if (TSF1_savedcxt) MemoryContextSwitchTo(TSF1_savedcxt);
		SRF_RETURN_DONE(funcctx);
	}
}
Example #22
0
static PyObj
statement_first(PyObj self, PyObj args, PyObj kw)
{
	MemoryContext former = CurrentMemoryContext;
	PyObj c, rob = NULL;

	if (resolve_parameters(self, &args, &kw))
		return(NULL);

	if (DB_IS_NOT_READY())
		return(NULL);

	if (PyPgStatement_ReturnsRows(self))
	{
		c = PyPgCursor_New(self, args, kw, CUR_ROWS(1));

		if (c != NULL)
		{
			PyObj r;

			r = PyIter_Next(c);
			if (!PyErr_Occurred() && r == NULL)
			{
				r = Py_None;
				Py_INCREF(r);
			}

			if (PyPgCursor_Close(c))
			{
				Py_DECREF(c);
				Py_XDECREF(r);
				return(NULL);
			}

			if (r != NULL)
			{
				if (r == Py_None)
					rob = r;
				else
				{
					Py_ssize_t s = PySequence_Size(r);

					if (s == -1)
						rob = NULL;
					else if (s == 1)
					{
						rob = PySequence_GetItem(r, 0);
						Py_DECREF(r);
					}
					else
					{
						/*
						 * It has multiple columns, so return the first row.
						 */
						rob = r;
					}
				}
			}
			Py_DECREF(c);
		}
	}
	else
	{
		SPIPlanPtr plan;
		PyObj tdo = PyPgStatement_GetInput(self);
		TupleDesc td = PyPgTupleDesc_GetTupleDesc(tdo);
		PyObj pargs;

		plan = PyPgStatement_GetPlan(self);
		if (plan == NULL)
			return(NULL);

		pargs = Py_NormalizeRow(
			PyPgTupleDesc_GetNatts(tdo), td,
			PyPgTupleDesc_GetNameMap(tdo),
			args
		);
		if (pargs == NULL)
			return(NULL);

		PG_TRY();
		{
			int r;
			Datum *datums;
			bool *nulls;
			char *cnulls;
			int *freemap = PyPgTupleDesc_GetFreeMap(tdo);

			datums = palloc(sizeof(Datum) * td->natts);
			nulls = palloc(sizeof(bool) * td->natts);
			cnulls = palloc(sizeof(char) * td->natts);

			Py_BuildDatumsAndNulls(
				td, PyPgTupleDesc_GetTypesTuple(tdo), pargs,
				datums, nulls
			);

			for (r = 0; r < td->natts; ++r)
			{
				cnulls[r] = nulls[r] ? 'n' : ' ';
			}
			r = SPI_execute_plan(plan, datums, cnulls, PL_FN_READONLY(), 1);
			if (r < 0)
				raise_spi_error(r);
			rob = PyLong_FromUnsignedLong(SPI_processed);

			FreeDatumsAndNulls(freemap, datums, nulls);
			pfree(cnulls);
		}
		PG_CATCH();
		{
			PyErr_SetPgError(false);
			Py_XDECREF(rob);
			rob = NULL;
		}
		PG_END_TRY();

		Py_DECREF(pargs);
	}
	MemoryContextSwitchTo(former);

	return(rob);
}
Example #23
0
/* Clause 3.3.9.4 */
Datum TradeUpdateFrame2(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	AttInMetadata *attinmeta;
	int call_cntr;
	int max_calls;

	int i;
	int j;

	char **values = NULL;

	/* Stuff done only on the first call of the function. */
	if (SRF_IS_FIRSTCALL()) {
		MemoryContext oldcontext;

		enum tuf2 {
				i_bid_price=0, i_cash_transaction_amount,
				i_cash_transaction_dts, i_cash_transaction_name, i_exec_name,
				i_is_cash, i_num_found, i_num_updated, i_settlement_amount,
				i_settlement_cash_due_date, i_settlement_cash_type,
				i_trade_history_dts, i_trade_history_status_id, i_trade_list,
				i_trade_price
		};

		long acct_id = PG_GETARG_INT64(0);
		Timestamp end_trade_dts_ts = PG_GETARG_TIMESTAMP(1);
		int max_trades = PG_GETARG_INT32(2);
		int max_updates = PG_GETARG_INT32(3);
		Timestamp start_trade_dts_ts = PG_GETARG_TIMESTAMP(4);

		int ret;
		TupleDesc tupdesc;
		SPITupleTable *tuptable = NULL;
		HeapTuple tuple = NULL;

		struct pg_tm tt, *tm = &tt;
		fsec_t fsec;
		char *tzn = NULL;
#ifdef DEBUG
		char sql[2048];
#endif
		Datum args[4];
		char nulls[4] = { ' ', ' ', ' ', ' ' };

		char end_trade_dts[MAXDATELEN + 1];
		char start_trade_dts[MAXDATELEN + 1];

		int num_found;
		int num_updated = 0;
		int num_cash = 0;

		if (timestamp2tm(end_trade_dts_ts, NULL, tm, &fsec, NULL, NULL) == 0) {
			EncodeDateTimeM(tm, fsec, tzn, end_trade_dts);
		}
		if (timestamp2tm(start_trade_dts_ts, NULL, tm, &fsec, NULL, NULL) ==
				0) {
			EncodeDateTimeM(tm, fsec, tzn, start_trade_dts);
		}

#ifdef DEBUG
		dump_tuf2_inputs(acct_id, end_trade_dts, max_trades, max_updates,
				start_trade_dts);
#endif

		/*
		 * Prepare a values array for building the returned tuple.
		 * This should be an array of C strings, which will
		 * be processed later by the type input functions.
		 * Don't forget to factor in commas (,) and braces ({}) for the arrays.
		 */
		values = (char **) palloc(sizeof(char *) * 15);
		values[i_bid_price] =
				(char *) palloc(((S_PRICE_T_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_cash_transaction_amount] =
				(char *) palloc(((VALUE_T_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_cash_transaction_dts] =
				(char *) palloc(((MAXDATELEN + 1) * 20 + 2) * sizeof(char));
		values[i_cash_transaction_name] =
				(char *) palloc(((CT_NAME_LEN + 3) * 20 + 2) * sizeof(char));
		values[i_exec_name] = (char *) palloc(((T_EXEC_NAME_LEN + 3) * 20 +
				2) * sizeof(char));
		values[i_is_cash] =
				(char *) palloc(((SMALLINT_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_num_found] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
		values[i_num_updated] =
				(char *) palloc((INTEGER_LEN + 1) * sizeof(char));
		values[i_settlement_amount] =
				(char *) palloc(((VALUE_T_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_settlement_cash_due_date] =
				(char *) palloc(((MAXDATELEN + 1) * 20 + 2) * sizeof(char));
		values[i_settlement_cash_type] = (char *) palloc(((SE_CASH_TYPE_LEN +
				3) * 20 + 2) * sizeof(char));
		values[i_trade_history_dts] = (char *) palloc((((MAXDATELEN + 2) * 3
				+ 2) * 20 + 5) * sizeof(char));
		values[i_trade_history_status_id] = (char *) palloc((((ST_ID_LEN +
				2) * 3 + 2) * 20 + 5) * sizeof(char));
		values[i_trade_list] =
				(char *) palloc(((BIGINT_LEN + 1) * 20 + 2) * sizeof(char));
		values[i_trade_price] =
				(char *) palloc(((S_PRICE_T_LEN + 1) * 20 + 2) * sizeof(char));

		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();
		funcctx->max_calls = 1;

		/* switch to memory context appropriate for multiple function calls */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		SPI_connect();
		plan_queries(TUF2_statements);
#ifdef DEBUG
		sprintf(sql, SQLTUF2_1, acct_id, start_trade_dts, end_trade_dts,
				max_trades);
		elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
		args[0] = Int64GetDatum(acct_id);
		args[1] = TimestampGetDatum(start_trade_dts_ts);
		args[2] = TimestampGetDatum(end_trade_dts_ts);
		args[3] = Int32GetDatum(max_trades);
		ret = SPI_execute_plan(TUF2_1, args, nulls, true, 0);
		if (ret == SPI_OK_SELECT && SPI_processed > 0) {
			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
		}

		num_found = SPI_processed;

		strcpy(values[i_bid_price], "{");
		strcpy(values[i_exec_name], "{");
		strcpy(values[i_is_cash], "{");
		strcpy(values[i_trade_list], "{");
		strcpy(values[i_trade_price], "{");
		strcpy(values[i_settlement_amount], "{");
		strcpy(values[i_settlement_cash_due_date], "{");
		strcpy(values[i_settlement_cash_type], "{");
		strcpy(values[i_cash_transaction_amount], "{");
		strcpy(values[i_cash_transaction_dts], "{");
		strcpy(values[i_cash_transaction_name], "{");
		strcpy(values[i_trade_history_dts], "{");
		strcpy(values[i_trade_history_status_id], "{");
		for (i = 0; i < num_found; i++) {
			TupleDesc l_tupdesc;
			SPITupleTable *l_tuptable = NULL;
			HeapTuple l_tuple = NULL;

			char *is_cash_str;
			char *trade_list;
			char cash_type[41];

			tuple = tuptable->vals[i];

			if (i > 0) {
				strcat(values[i_bid_price], ",");
				strcat(values[i_exec_name], ",");
				strcat(values[i_is_cash], ",");
				strcat(values[i_trade_list], ",");
				strcat(values[i_trade_price], ",");
				strcat(values[i_settlement_amount], ",");
				strcat(values[i_settlement_cash_due_date], ",");
				strcat(values[i_settlement_cash_type], ",");
				strcat(values[i_trade_history_dts], ",");
				strcat(values[i_trade_history_status_id], ",");
			}

			strcat(values[i_bid_price], SPI_getvalue(tuple, tupdesc, 1));
			strcat(values[i_exec_name], "\"");
			strcat(values[i_exec_name], SPI_getvalue(tuple, tupdesc, 2));
			strcat(values[i_exec_name], "\"");
			is_cash_str = SPI_getvalue(tuple, tupdesc, 3);
			strcat(values[i_is_cash], (is_cash_str[0] == 't' ? "0" : "1"));
			trade_list = SPI_getvalue(tuple, tupdesc, 4);
			strcat(values[i_trade_list], trade_list);
			strcat(values[i_trade_price], SPI_getvalue(tuple, tupdesc, 5));

			if (num_updated < max_updates) {
				char *old_cash_type;

#ifdef DEBUG
				sprintf(sql, SQLTUF2_2, trade_list);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[0] = Int64GetDatum(atoll(trade_list));
				ret = SPI_execute_plan(TUF2_2, args, nulls, true, 0);
				if (ret == SPI_OK_SELECT && SPI_processed > 0) {
					l_tupdesc = SPI_tuptable->tupdesc;
					l_tuptable = SPI_tuptable;
					l_tuple = l_tuptable->vals[0];
					old_cash_type = SPI_getvalue(l_tuple, l_tupdesc, 1);
				} else {
					FAIL_FRAME_SET(&funcctx->max_calls,
								TUF2_statements[1].sql);
					dump_tuf2_inputs(acct_id, end_trade_dts, max_trades,
							max_updates, start_trade_dts);
					continue;
				}

#ifdef DEBUG
				elog(NOTICE, "cash_type = '%s'", old_cash_type);
#endif /* DEBUG */

				if (is_cash_str[0] == 't') {
					if (strcmp(old_cash_type, "Cash Account") == 0) {
						strcpy(cash_type, "Cash");
					} else {
						strcpy(cash_type, "Cash Account");
					}
				} else {
					if (strcmp(old_cash_type, "Margin Account") == 0) {
						strcpy(cash_type, "Margin");
					} else {
						strcpy(cash_type, "Margin Account");
					}
				}

#ifdef DEBUG
				sprintf(sql, SQLTUF2_3, cash_type, trade_list);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[0] = CStringGetTextDatum(cash_type);
				args[1] = Int64GetDatum(atoll(trade_list));
				ret = SPI_execute_plan(TUF2_3, args, nulls, false, 0);
				if (ret != SPI_OK_UPDATE) {
					FAIL_FRAME_SET(&funcctx->max_calls,
								TUF2_statements[2].sql);
					dump_tuf2_inputs(acct_id, end_trade_dts, max_trades,
							max_updates, start_trade_dts);
					continue;
				}
				num_updated += SPI_processed;
			}

#ifdef DEBUG
			sprintf(sql, SQLTUF2_4, trade_list);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			args[0] = Int64GetDatum(atoll(trade_list));
			ret = SPI_execute_plan(TUF2_4, args, nulls, true, 0);
			if (ret == SPI_OK_SELECT && SPI_processed > 0) {
				l_tupdesc = SPI_tuptable->tupdesc;
				l_tuptable = SPI_tuptable;
				l_tuple = l_tuptable->vals[0];
				strcat(values[i_settlement_amount],
						SPI_getvalue(l_tuple, l_tupdesc, 1));
				strcat(values[i_settlement_cash_due_date],
						SPI_getvalue(l_tuple, l_tupdesc, 2));
				strcat(values[i_settlement_cash_type], "\"");
				strcat(values[i_settlement_cash_type],
						SPI_getvalue(l_tuple, l_tupdesc, 3));
				strcat(values[i_settlement_cash_type], "\"");
			} else {
				FAIL_FRAME_SET(&funcctx->max_calls,
							TUF2_statements[3].sql);
				dump_tuf2_inputs(acct_id, end_trade_dts, max_trades,
						max_updates, start_trade_dts);
				continue;
			}

			if (is_cash_str[0] == 't') {
#ifdef DEBUG
				sprintf(sql, SQLTUF2_5, trade_list);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				ret = SPI_execute_plan(TUF2_5, args, nulls, true, 0);
				if (ret == SPI_OK_SELECT && SPI_processed > 0) {
					l_tupdesc = SPI_tuptable->tupdesc;
					l_tuptable = SPI_tuptable;
					l_tuple = l_tuptable->vals[0];
					if (num_cash > 0) {
						strcat(values[i_cash_transaction_amount], ",");
						strcat(values[i_cash_transaction_dts], ",");
						strcat(values[i_cash_transaction_name], ",");
					}
					strcat(values[i_cash_transaction_amount],
							SPI_getvalue(l_tuple, l_tupdesc, 1));
					strcat(values[i_cash_transaction_dts],
							SPI_getvalue(l_tuple, l_tupdesc, 2));
					strcat(values[i_cash_transaction_name], "\"");
					strcat(values[i_cash_transaction_name],
							SPI_getvalue(l_tuple, l_tupdesc, 3));
					strcat(values[i_cash_transaction_name], "\"");
					++num_cash;
				} else {
					FAIL_FRAME_SET(&funcctx->max_calls,
								TUF2_statements[4].sql);
					dump_tuf2_inputs(acct_id, end_trade_dts, max_trades,
							max_updates, start_trade_dts);
					continue;
				}
			} else {
					if (num_cash > 0) {
						strcat(values[i_cash_transaction_amount], ",");
						strcat(values[i_cash_transaction_dts], ",");
						strcat(values[i_cash_transaction_name], ",");
					}
					strcat(values[i_cash_transaction_amount], "0");
					strcat(values[i_cash_transaction_dts], "1970-1-1 0:0:0");
					strcat(values[i_cash_transaction_name], "\"\"");
					++num_cash;
			}

#ifdef DEBUG
			sprintf(sql, SQLTUF2_6, trade_list);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */

			ret = SPI_execute_plan(TUF2_6, args, nulls, true, 0);
			if (ret == SPI_OK_SELECT && SPI_processed > 0) {
				l_tupdesc = SPI_tuptable->tupdesc;
				l_tuptable = SPI_tuptable;
			} else {
				FAIL_FRAME_SET(&funcctx->max_calls, TUF2_statements[5].sql);
				dump_tuf2_inputs(acct_id, end_trade_dts, max_trades,
						max_updates, start_trade_dts);
				continue;
			}
			strcat(values[i_trade_history_dts], "{");
			strcat(values[i_trade_history_status_id], "{");
			for (j = 0; j < SPI_processed; j ++) {
				if (j > 0) {
					strcat(values[i_trade_history_dts], ",");
					strcat(values[i_trade_history_status_id], ",");
				}
				l_tuple = l_tuptable->vals[j];
				strcat(values[i_trade_history_dts],
							SPI_getvalue(l_tuple, l_tupdesc, 1));
				strcat(values[i_trade_history_status_id], "\"");
				strcat(values[i_trade_history_status_id],
							SPI_getvalue(l_tuple, l_tupdesc, 2));
				strcat(values[i_trade_history_status_id], "\"");
			}
                        for (j = SPI_processed; j < 3; j++) {
                                if (j > 0) {
                                        strcat(values[i_trade_history_dts], ",");
                                        strcat(values[i_trade_history_status_id], ",");
                                }
                                strcat(values[i_trade_history_dts], "NULL");
                                strcat(values[i_trade_history_status_id], "\"\"");
                        }
			strcat(values[i_trade_history_dts], "}");
			strcat(values[i_trade_history_status_id], "}");
		}
		strcat(values[i_bid_price], "}");
		strcat(values[i_exec_name], "}");
		strcat(values[i_is_cash], "}");
		strcat(values[i_trade_list], "}");
		strcat(values[i_trade_price], "}");
		strcat(values[i_settlement_amount], "}");
		strcat(values[i_settlement_cash_due_date], "}");
		strcat(values[i_settlement_cash_type], "}");
		strcat(values[i_cash_transaction_amount], "}");
		strcat(values[i_cash_transaction_dts], "}");
		strcat(values[i_cash_transaction_name], "}");
		strcat(values[i_trade_history_dts], "}");
		strcat(values[i_trade_history_status_id], "}");

		sprintf(values[i_num_found], "%d", num_found);
		sprintf(values[i_num_updated], "%d", num_updated);

		/* 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")));
		}

		/*
		 * generate attribute metadata needed later to produce tuples from raw
		 * C strings
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	attinmeta = funcctx->attinmeta;

	if (call_cntr < max_calls) {
		/* do when there is more left to send */
		HeapTuple tuple;
		Datum result;

#ifdef DEBUG
		for (i = 0; i < 15; i++) {
			elog(NOTICE, "TUF2 OUT: %d %s", i, values[i]);
		}
#endif /* DEBUG */

		/* Build a tuple. */
		tuple = BuildTupleFromCStrings(attinmeta, values);

		/* Make the tuple into a datum. */
		result = HeapTupleGetDatum(tuple);

		SRF_RETURN_NEXT(funcctx, result);
	} else {
		/* Do when there is no more left. */
		SPI_finish();
		SRF_RETURN_DONE(funcctx);
	}
}
Example #24
0
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 *buf;

	Datum args[5];
	char nulls[5] = { ' ', ' ', ' ', ' ', ' ' };

	SPI_connect();

	plan_queries(statements);

	args[0] = Int32GetDatum(w_id);
	args[1] = Int32GetDatum(d_id);
	ret = SPI_execute_plan(STOCK_LEVEL_1, args, nulls, true, 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);
		elog(DEBUG1, "d_next_o_id = %s", buf);
		d_next_o_id = atoi(buf);
	} else {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	args[0] = Int32GetDatum(w_id);
	args[1] = Int32GetDatum(d_id);
	args[2] = Int32GetDatum(threshold);
	args[3] = Int32GetDatum(d_next_o_id - 20);
	args[4] = Int32GetDatum(d_next_o_id - 1);
	ret = SPI_execute_plan(STOCK_LEVEL_2, args, nulls, true, 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);
		elog(DEBUG1, "low_stock = %s", buf);
		low_stock = atoi(buf);
	} else {
		SPI_finish();
		PG_RETURN_INT32(-1);
	}

	SPI_finish();
	PG_RETURN_INT32(low_stock);
}
Example #25
0
/* Clause 3.3.1.3 */
Datum MarketFeedFrame1(PG_FUNCTION_ARGS)
{
	FuncCallContext *funcctx;
	AttInMetadata *attinmeta;
	int call_cntr;
	int max_calls;

	int i, j, n;
	int num_updated = 0;
	int rows_sent;
	int send_len = 0;
	int count = 0;

	int nitems_pq;
	int *p_tq;
	char *p_s;

	char **values = NULL;

	/* Stuff done only on the first call of the function. */
	if (SRF_IS_FIRSTCALL()) {
		MemoryContext oldcontext;

		ArrayType *price_quote_p = PG_GETARG_ARRAYTYPE_P(0);
		char *status_submitted_p = (char *) PG_GETARG_TEXT_P(1);
		ArrayType *symbol_p = PG_GETARG_ARRAYTYPE_P(2);
		ArrayType *trade_qty = PG_GETARG_ARRAYTYPE_P(3);
		char *type_limit_buy_p = (char *) PG_GETARG_TEXT_P(4);
		char *type_limit_sell_p = (char *) PG_GETARG_TEXT_P(5);
		char *type_stop_loss_p = (char *) PG_GETARG_TEXT_P(6);

		enum mff1 {
				i_num_updated=0, i_send_len, i_symbol, i_trade_id,
				i_price_quote, i_trade_qty, i_trade_type
		};

		Datum *transdatums_pq;

		int16 typlen_s;
		bool typbyval_s;
		char typalign_s;

		int16 typlen_tq;
		bool typbyval_tq;
		char typalign_tq;

		int ret;
		TupleDesc tupdesc;
		SPITupleTable *tuptable = NULL;
		HeapTuple tuple = NULL;
#ifdef DEBUG
		char sql[2048];
#endif
		Datum args[7];
		char nulls[] = { ' ', ' ', ' ', ' ', ' ',
						' ', ' ' };
		char price_quote[S_PRICE_T_LEN + 1];
		char status_submitted[ST_ID_LEN + 1];
		char symbol[S_SYMB_LEN + 1];
		char type_limit_buy[TT_ID_LEN + 1];
		char type_limit_sell[TT_ID_LEN + 1];
		char type_stop_loss[TT_ID_LEN + 1];
		char *trade_id;
		char *req_price_quote;
		char *req_trade_type;
		char *req_trade_qty;

		/*
		 * Prepare a values array for building the returned tuple.
		 * This should be an array of C strings, which will
		 * be processed later by the type input functions.
		 */
		values = (char **) palloc(sizeof(char *) * 7);
		values[i_num_updated] =
				(char *) palloc((INTEGER_LEN + 1) * sizeof(char));
		values[i_send_len] = (char *) palloc((INTEGER_LEN + 1) * sizeof(char));
		/*
		 * FIXME: We don't know how many rows could be returned.  The average
		 * is supposed to be 4.  Let's be prepared for 100, just to be safe.
		 */
		values[i_symbol] = (char *) palloc(((S_SYMB_LEN + 3) * 100 + 3) *
				sizeof(char));
		values[i_trade_id] = (char *) palloc(((IDENT_T_LEN + 1) * 100 + 2) *
				sizeof(char));
		values[i_price_quote] = (char *) palloc(((S_PRICE_T_LEN + 1) * 100 +
				2) * sizeof(char));
		values[i_trade_qty] = (char *) palloc(((INTEGER_LEN + 1) * 100 + 2) *
				sizeof(char));
		values[i_trade_type] = (char *) palloc(((TT_ID_LEN + 3) * 100 + 3) *
				sizeof(char));

		/*
		 * This might be overkill since we always expect single dimensions
		 * arrays.
		 * Should probably check the count of all the arrays to make sure
		 * they are the same...
		 */
		get_typlenbyvalalign(ARR_ELEMTYPE(symbol_p), &typlen_s, &typbyval_s,
				&typalign_s);
		p_s = ARR_DATA_PTR(symbol_p);

		get_typlenbyvalalign(ARR_ELEMTYPE(trade_qty), &typlen_tq, &typbyval_tq,
				&typalign_tq);
		p_tq = (int *) ARR_DATA_PTR(trade_qty);

		deconstruct_array(price_quote_p, NUMERICOID, -1, false, 'i',
				&transdatums_pq, NULL, &nitems_pq);

		strcpy(status_submitted, DatumGetCString(DirectFunctionCall1(textout,
				PointerGetDatum(status_submitted_p))));
		strcpy(type_limit_buy, DatumGetCString(DirectFunctionCall1(textout,
				PointerGetDatum(type_limit_buy_p))));
        strcpy(type_limit_sell, DatumGetCString(DirectFunctionCall1(textout,
                PointerGetDatum(type_limit_sell_p))));
		strcpy(type_stop_loss, DatumGetCString(DirectFunctionCall1(textout,
                PointerGetDatum(type_stop_loss_p))));

#ifdef DEBUG
		dump_mff1_inputs(price_quote_p, status_submitted_p, symbol_p,
				trade_qty, type_limit_buy_p, type_limit_sell_p,
				type_stop_loss_p);
#endif

		/* create a function context for cross-call persistence */
		funcctx = SRF_FIRSTCALL_INIT();

		/* switch to memory context appropriate for multiple function calls */
		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

		SPI_connect();
		plan_queries(MFF1_statements);

		strcpy(values[i_symbol], "{");
		strcpy(values[i_trade_id], "{");
		strcpy(values[i_price_quote], "{");
		strcpy(values[i_trade_type], "{");
		strcpy(values[i_trade_qty], "{");
		for (i = 0; i < nitems_pq; i++) {
			rows_sent = 0;

			strcpy(price_quote,
					DatumGetCString(DirectFunctionCall1(numeric_out,
							transdatums_pq[i])));
			strcpy(symbol, DatumGetCString(DirectFunctionCall1(textout,
					PointerGetDatum(p_s))));
			/* FIXME: BEGIN/COMMIT statements not supported with SPI. */
/*
			ret = SPI_exec("BEGIN;", 0);
			if (ret == SPI_OK_SELECT) {
			} else {
				elog(NOTICE, "ERROR: BEGIN not ok = %d", ret);
			}
*/
#ifdef DEBUG
			sprintf(sql, SQLMFF1_1,
					DatumGetCString(DirectFunctionCall1(numeric_out,            
							transdatums_pq[i])),
					p_tq[i],
					symbol);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			args[0] = Float8GetDatum(atof(price_quote));
			args[1] = Int64GetDatum(p_tq[i]);
			args[2] = CStringGetTextDatum(symbol);
			ret = SPI_execute_plan(MFF1_1, args, nulls, false, 0);
			if (ret != SPI_OK_UPDATE) {
				dump_mff1_inputs(price_quote_p, status_submitted_p, symbol_p,
						trade_qty, type_limit_buy_p, type_limit_sell_p,
						type_stop_loss_p);
				FAIL_FRAME_SET(&funcctx->max_calls, MFF1_statements[0].sql);
			}
			num_updated += SPI_processed;
#ifdef DEBUG
			elog(NOTICE, "%d row(s) updated", num_updated);
			sprintf(sql, SQLMFF1_2, symbol, type_stop_loss, price_quote,
					type_limit_sell, price_quote, type_limit_buy, price_quote);
			elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
			args[0] = CStringGetTextDatum(symbol);
			args[1] = CStringGetTextDatum(type_stop_loss);
			args[2] = Float8GetDatum(atof(price_quote));
			args[3] = CStringGetTextDatum(type_limit_sell);
			args[4] = args[2];
			args[5] = CStringGetTextDatum(type_limit_buy);
			args[6] = args[2];
			ret = SPI_execute_plan(MFF1_2, args, nulls, true, 0);
			if (ret != SPI_OK_SELECT) {
				dump_mff1_inputs(price_quote_p, status_submitted_p, symbol_p,
						trade_qty, type_limit_buy_p, type_limit_sell_p,
						type_stop_loss_p);
				FAIL_FRAME_SET(&funcctx->max_calls, MFF1_statements[1].sql);
				continue;
			}
#ifdef DEBUG
			elog(NOTICE, "%d row(s) returned", SPI_processed);
#endif /* DEBUG */

			tupdesc = SPI_tuptable->tupdesc;
			tuptable = SPI_tuptable;
			n = SPI_processed;
			for (j = 0; j < n; j++) {
				tuple = tuptable->vals[j];
				trade_id = SPI_getvalue(tuple, tupdesc, 1);
				req_price_quote = SPI_getvalue(tuple, tupdesc, 2);
				req_trade_type = SPI_getvalue(tuple, tupdesc, 3);
				req_trade_qty = SPI_getvalue(tuple, tupdesc, 4);
#ifdef DEBUG
				elog(NOTICE, "trade_id = %s", trade_id);
				sprintf(sql, SQLMFF1_3, status_submitted, trade_id);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[0] = CStringGetTextDatum(status_submitted);
				args[1] = Int64GetDatum(atoll(trade_id));
				ret = SPI_execute_plan(MFF1_3, args, nulls, false, 0);
				if (ret != SPI_OK_UPDATE) {
					dump_mff1_inputs(price_quote_p, status_submitted_p,
							symbol_p, trade_qty, type_limit_buy_p,
							type_limit_sell_p, type_stop_loss_p);
					FAIL_FRAME_SET(&funcctx->max_calls, MFF1_statements[2].sql);
				}
#ifdef DEBUG
				sprintf(sql, SQLMFF1_4, trade_id);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[0] = Int64GetDatum(atoll(trade_id));
				ret = SPI_execute_plan(MFF1_4, args, nulls, false, 0);
				if (ret != SPI_OK_DELETE) {
					dump_mff1_inputs(price_quote_p, status_submitted_p,
							symbol_p, trade_qty, type_limit_buy_p,
							type_limit_sell_p, type_stop_loss_p);
					FAIL_FRAME_SET(&funcctx->max_calls, MFF1_statements[3].sql);
				}
#ifdef DEBUG
				sprintf(sql, SQLMFF1_5, trade_id, status_submitted);
				elog(NOTICE, "SQL\n%s", sql);
#endif /* DEBUG */
				args[1] = CStringGetTextDatum(status_submitted);
				ret = SPI_execute_plan(MFF1_5, args, nulls, false, 0);
				if (ret != SPI_OK_INSERT) {
					dump_mff1_inputs(price_quote_p, status_submitted_p,
							symbol_p, trade_qty, type_limit_buy_p,
							type_limit_sell_p, type_stop_loss_p);
					FAIL_FRAME_SET(&funcctx->max_calls, MFF1_statements[4].sql);
				}
				++rows_sent;
#ifdef DEBUG
				elog(NOTICE, "%d row(s) sent", rows_sent);
#endif /* DEBUG */

				if (count > 0) {
					strcat(values[i_symbol], ",");
					strcat(values[i_trade_id], ",");
					strcat(values[i_price_quote], ",");
					strcat(values[i_trade_type], ",");
					strcat(values[i_trade_qty], ",");
				}
				strcat(values[i_symbol], symbol);
				strcat(values[i_trade_id], trade_id);
				strcat(values[i_price_quote], req_price_quote);
				strcat(values[i_trade_type], req_trade_type);
				strcat(values[i_trade_qty], req_trade_qty);
				++count;
			}

			/* FIXME: BEGIN/COMMIT statements not supported with SPI. */
/*
			ret = SPI_exec("COMMIT;", 0);
			if (ret == SPI_OK_SELECT) {
			} else {
				elog(NOTICE, "ERROR: COMMIT not ok = %d", ret);
			}
*/

			send_len += rows_sent;

			p_s = att_addlength_pointer(p_s, typlen_s, p_s);
			p_s = (char *) att_align_nominal(p_s, typalign_s);
		}
		strcat(values[i_symbol], "}");
		strcat(values[i_trade_id], "}");
		strcat(values[i_price_quote], "}");
		strcat(values[i_trade_qty], "}");
		strcat(values[i_trade_type], "}");

		sprintf(values[i_num_updated], "%d", num_updated);
		sprintf(values[i_send_len], "%d", send_len);
		funcctx->max_calls = 1;

		/* 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")));
		}

		/*
		 * generate attribute metadata needed later to produce tuples from raw
		 * C strings
		 */
		attinmeta = TupleDescGetAttInMetadata(tupdesc);
		funcctx->attinmeta = attinmeta;

		MemoryContextSwitchTo(oldcontext);
	}

	/* stuff done on every call of the function */
	funcctx = SRF_PERCALL_SETUP();

	call_cntr = funcctx->call_cntr;
	max_calls = funcctx->max_calls;
	attinmeta = funcctx->attinmeta;

	if (call_cntr < max_calls) {
		/* do when there is more left to send */
		HeapTuple tuple;
		Datum result;

#ifdef DEBUG                                                                    
		for (i = 0; i < 7; i++) {
			elog(NOTICE, "MFF1 OUT: %d %s", i, values[i]);
		}
#endif /* DEBUG */

		/* Build a tuple. */
		tuple = BuildTupleFromCStrings(attinmeta, values);

		/* Make the tuple into a datum. */
		result = HeapTupleGetDatum(tuple);

		SRF_RETURN_NEXT(funcctx, result);
	} else {
		/* Do when there is no more left. */
		SPI_finish();
		SRF_RETURN_DONE(funcctx);
	}
}
Example #26
0
/*
 * Arguments:
 * 0: queue_name  text          NOT NULL
 * 1: ev_id       int8			if NULL take from SEQ
 * 2: ev_time     timestamptz   if NULL use now()
 * 3: ev_owner    int4
 * 4: ev_retry    int4
 * 5: ev_type     text
 * 6: ev_data     text
 * 7: ev_extra1   text
 * 8: ev_extra2   text
 * 9: ev_extra3   text
 * 10:ev_extra4   text
 */
Datum
pgq_insert_event_raw(PG_FUNCTION_ARGS)
{
	Datum values[11];
	char nulls[11];
	struct QueueState state;
	int64 ret_id;
	void *ins_plan;
	Datum ev_id, ev_time;
	int i, res;

	if (PG_NARGS() < 6)
		elog(ERROR, "Need at least 6 arguments");
	if (PG_ARGISNULL(0))
		elog(ERROR, "Queue name must not be NULL");

	if (SPI_connect() < 0)
		elog(ERROR, "SPI_connect() failed");
	
	init_cache();

	load_queue_info(PG_GETARG_DATUM(0), &state);

	if (PG_ARGISNULL(1))
		ev_id = state.next_event_id;
	else
		ev_id = PG_GETARG_DATUM(1);

	if (PG_ARGISNULL(2))
		ev_time = DirectFunctionCall1(now, 0);
	else
		ev_time = PG_GETARG_DATUM(2);

	/*
	 * Prepare arguments for INSERT
	 */
	values[0] = ev_id;
	nulls[0] = ' ';
	values[1] = ev_time;
	nulls[1] = ' ';
	for (i = 3; i < 11; i++) {
		int dst = i - 1;
		if (i >= PG_NARGS() || PG_ARGISNULL(i)) {
			values[dst] = (Datum)NULL;
			nulls[dst] = 'n';
		} else {
			values[dst] = PG_GETARG_DATUM(i);
			nulls[dst] = ' ';
		}
	}

	/*
	 * Perform INSERT into queue table.
	 */
	ins_plan = load_insert_plan(&state);
	res = SPI_execute_plan(ins_plan, values, nulls, false, 0);
	if (res != SPI_OK_INSERT)
		elog(ERROR, "Queue insert failed");

	/*
	 * ev_id cannot pass SPI_finish()
	 */
	ret_id = DatumGetInt64(ev_id);

	if (SPI_finish() < 0)
		elog(ERROR, "SPI_finish failed");

	PG_RETURN_INT64(ret_id);
}
Example #27
0
/* Obsolete version of SPI_execute_plan */
int
SPI_execp(void *plan, Datum *Values, const char *Nulls, long tcount)
{
	return SPI_execute_plan(plan, Values, Nulls, false, tcount);
}
Example #28
0
Datum
exec_sql_using(PG_FUNCTION_ARGS) {
    HeapTuple procedureTuple = SearchSysCache1(PROCOID,
        ObjectIdGetDatum(fcinfo->flinfo->fn_oid));
    if (!HeapTupleIsValid(procedureTuple))
        ereport(ERROR,
            (errmsg("cache lookup failed for function %u",
            fcinfo->flinfo->fn_oid)));

    Oid* types = NULL;
    char** names = NULL;
    char* modes = NULL;
    int nargs = get_func_arg_info(procedureTuple, &types, &names, &modes);

    Oid resultTypeOid;
    TupleDesc tupleDesc;
    TypeFuncClass resultType = get_call_result_type(fcinfo, &resultTypeOid,
        &tupleDesc);
    bool returnTypeIsByValue;
    int16 returnTypeLen;
    get_typlenbyval(resultTypeOid, &returnTypeLen, &returnTypeIsByValue);

    if (resultType != TYPEFUNC_SCALAR && resultType != TYPEFUNC_COMPOSITE)
        ereport(ERROR, (
            errmsg("function \"%s\" has indeterminable result type",
                format_procedure(fcinfo->flinfo->fn_oid))
            ));
    bool returnVoid = resultTypeOid == VOIDOID;

    ReleaseSysCache(procedureTuple);

    if (nargs < 2)
        ereport(ERROR, (
            errmsg("function \"%s\" has less than 2 arguments",
                format_procedure(fcinfo->flinfo->fn_oid))
            ));
    else if (modes != NULL)
        for (int i = 0; i < nargs; i++) {
            if (modes[i] != PROARGMODE_IN)
                ereport(ERROR, (
                    errmsg("function \"%s\" has non-IN arguments",
                        format_procedure(fcinfo->flinfo->fn_oid))
                    ));
        }
    else if (PG_ARGISNULL(0))
        ereport(ERROR, (
            errmsg("function \"%s\" called with NULL as first argument",
                format_procedure(fcinfo->flinfo->fn_oid))
            ));

    char* stmt = NULL;
    if (types[0] == TEXTOID)
        stmt = DatumGetCString(
            DirectFunctionCall1(textout, PG_GETARG_DATUM(0)));
    else if (types[0] == VARCHAROID)
        stmt = DatumGetCString(
            DirectFunctionCall1(varcharout, PG_GETARG_DATUM(0)));
    else
        ereport(ERROR, (
            errmsg("function \"%s\" does not have a leading VARCHAR/TEXT "
                "argument",
                format_procedure(fcinfo->flinfo->fn_oid))
            ));

    char* nulls = NULL;
    for (int i = 1; i < nargs; i++)
        if (PG_ARGISNULL(i)) {
            if (nulls == NULL) {
                nulls = palloc0(sizeof(char) * (nargs - 1));
                memset(nulls, ' ', nargs - 1);
            }
            nulls[i - 1] = 'n';
        }

    SPI_connect();
    SPIPlanPtr plan = SPI_prepare(stmt, nargs - 1, &types[1]);
    if (plan == NULL)
        ereport(ERROR, (
            errmsg("function \"%s\" could not obtain execution plan for "
                "SQL statement",
                format_procedure(fcinfo->flinfo->fn_oid))
            ));

    int result = SPI_execute_plan(plan, &fcinfo->arg[1], nulls, false,
        returnVoid ? 0 : 1);

    Datum returnValue = 0;
    bool returnNull = false;
    if (!returnVoid) {
        if (result != SPI_OK_SELECT
            && result != SPI_OK_INSERT_RETURNING
            && result != SPI_OK_DELETE_RETURNING
            && result == SPI_OK_UPDATE_RETURNING)
            ereport(ERROR, (
                errmsg("function \"%s\" could not obtain result from query",
                    format_procedure(fcinfo->flinfo->fn_oid))
                ));
        else if (SPI_tuptable->tupdesc->natts != 1)
            ereport(ERROR, (
                errmsg("function \"%s\" retrieved more than one column from "
                    "query",
                    format_procedure(fcinfo->flinfo->fn_oid))
                ));
        else if (resultTypeOid != SPI_gettypeid(SPI_tuptable->tupdesc, 1))
            ereport(ERROR, (
                errmsg("function \"%s\" has different return type OID than "
                    "what query returned",
                    format_procedure(fcinfo->flinfo->fn_oid))
                ));

        /* It is important to copy the value into the upper executor context,
         * i.e., the memory context that was current when SPI_connect was
         * called */
        returnValue = SPI_getbinval(SPI_copytuple(SPI_tuptable->vals[0]),
            SPI_tuptable->tupdesc, 1, &returnNull);
    }

    SPI_freeplan(plan);
    if (nulls)
        pfree(nulls);
    SPI_finish();

    if (result < 0)
        ereport(ERROR, (
            errmsg("function \"%s\" encountered error %d during SQL execution",
                format_procedure(fcinfo->flinfo->fn_oid),
                result)
            ));

    if (returnVoid)
        PG_RETURN_VOID();
    else if (returnNull)
        PG_RETURN_NULL();
    else
        return returnValue;
}