Exemplo n.º 1
0
static PyObj
func_new(PyTypeObject *subtype, PyObj args, PyObj kw)
{
	char *words[] = {"oid", NULL};
	Oid fn_oid = InvalidOid;
	PyObj source = NULL, lo, so, rob;

	if (DB_IS_NOT_READY())
		return(NULL);

	if (!PyArg_ParseTupleAndKeywords(args, kw, "O", words, &source))
		return(NULL);

	if (Oid_FromPyObject(source, &fn_oid))
		return(NULL);

	lo = PyLong_FromUnsignedLong(fn_oid);
	if (lo == NULL)
		return(NULL);
	so = PyObject_Str(lo);
	if (so == NULL)
	{
		Py_DECREF(lo);
		return(NULL);
	}

	rob = func_new_from_oid(subtype, fn_oid, lo, so);
	Py_DECREF(lo);
	Py_DECREF(so);

	return(rob);
}
Exemplo n.º 2
0
static PyObj
statement_load_rows(PyObj self, PyObj args, PyObj kw)
{
	char *words[] = {"rows_iter", NULL};
	PyObj row_iter, rob;
	uint32 total = 0;

	if (PyPgStatement_GetParameters(self) != Py_None)
	{
		PyErr_SetString(PyExc_TypeError,
			"cannot use load_rows with constant parameters");
		return(NULL);
	}

	if (!PyArg_ParseTupleAndKeywords(args, kw, "O:load_rows", words, &row_iter))
		return(NULL);

	if (DB_IS_NOT_READY())
		return(NULL);

	row_iter = PyObject_GetIter(row_iter);
	if (row_iter == NULL)
		return(NULL);

	if (load_rows(self, row_iter, &total))
		rob = NULL;
	else
		rob = PyLong_FromUnsignedLong(total);

	Py_DECREF(row_iter);

	return(rob);
}
Exemplo n.º 3
0
static PyObj
statement_clone(PyObj self)
{
	if (DB_IS_NOT_READY())
		return(NULL);

	return(PyPgStatement_NEW(
		Py_TYPE(self),
		PyPgStatement_GetString(self),
		PyPgStatement_GetParameters(self)
	));
}
Exemplo n.º 4
0
static PyObj
statement_load_chunks(PyObj self, PyObj args, PyObj kw)
{
	char *words[] = {"chunks_iter", NULL};
	PyObj chunk_iter, ob;
	uint32 total = 0;

	if (PyPgStatement_GetParameters(self) != Py_None)
	{
		PyErr_SetString(PyExc_TypeError,
			"cannot use load_rows with constant parameters");
		return(NULL);
	}

	if (!PyArg_ParseTupleAndKeywords(args, kw, "O:load_chunks", words, &chunk_iter))
		return(NULL);

	if (DB_IS_NOT_READY())
		return(NULL);

	chunk_iter = PyObject_GetIter(chunk_iter);
	if (chunk_iter == NULL)
		return(NULL);

	while ((ob = PyIter_Next(chunk_iter)))
	{
		PyObj row_iter;
		int r;

		row_iter = PyObject_GetIter(ob);
		Py_DECREF(ob);
		if (row_iter == NULL)
		{
			Py_DECREF(chunk_iter);
			return(NULL);
		}

		r = load_rows(self, row_iter, &total);
		Py_DECREF(row_iter);

		if (r)
		{
			Py_DECREF(chunk_iter);
			return(NULL);
		}
	}
	Py_DECREF(chunk_iter);

	return(PyLong_FromUnsignedLong(total));
}
Exemplo n.º 5
0
static PyObj
statement_declare(PyObj self, PyObj args, PyObj kw)
{
	if (DB_IS_NOT_READY())
		return(NULL);

	if (!PyPgStatement_ReturnsRows(self))
	{
		PyErr_SetString(PyExc_TypeError, "statement does not return rows");
		return(NULL);
	}

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

	return(PyPgCursor_New(self, args, kw, CUR_SCROLL_FORWARD));
}
Exemplo n.º 6
0
PyObj
PyPgObject_Operate(const char *op, PyObj fst, PyObj snd)
{
	PyObj rob;

	MemoryContext former;
	if (DB_IS_NOT_READY())
		return(NULL);

	former = CurrentMemoryContext;
	if (snd == NULL)
		rob = unary_operate(op, fst);
	else
		rob = binary_operate(op, fst, snd);
	MemoryContextSwitchTo(former);

	return(rob);
}
Exemplo n.º 7
0
static PyObj
obj_new(PyTypeObject *subtype, PyObj args, PyObj kw)
{
	static char *words[] = {"source", "mod", NULL};
	PyObj src = NULL, mod = NULL, rob = NULL, typmodin_ob = NULL;
	Datum d;
	bool isnull = true;
	int32 typmod = -1;

	if (DB_IS_NOT_READY())
		return(NULL);

	/*
	 * The type *must* be a PyPgType instance.
	 * Use CheckExact for speed.
	 * Subclassing PyPgType_Type is not supported.
	 */
	if (PyPgObjectType_Require(subtype))
		return(NULL);

	/*
	 * Grab a single "source" argument and an
	 * optional "mod" from the args and kw.
	 */
	if (!PyArg_ParseTupleAndKeywords(args, kw, "O|O", words, &src, &mod))
		return(NULL);

	if (mod != NULL && mod != Py_None)
	{
		PyObj lo;

		if (!PyList_CheckExact(mod))
		{
			lo = Py_Call((PyObj) &PyList_Type, mod);
			if (lo == NULL)
			{
				PyErr_SetString(PyExc_ValueError, "'mod' keyword must be a sequence");
				return(NULL);
			}
		}
		else
		{
			Py_INCREF(mod);
			lo = mod;
		}

		typmodin_ob = Py_Call(PyPg_cstring_Array_Type, lo);
		Py_DECREF(lo);
		if (typmodin_ob == NULL)
		{
			PyErr_SetString(PyExc_ValueError, "invalid typmod object");
			return(NULL);
		}
	}
	else if (Py_TYPE(src) == subtype)
	{
		/*
		 * Exact type and no typmod.
		 */
		rob = src;
		Py_INCREF(rob);
		return(rob);
	}

	PG_TRY();
	{
		if (typmodin_ob != NULL)
		{
			typmod = PyPgType_modin((PyObj) subtype, typmodin_ob);
		}

		if (src == Py_None)
		{
			d = 0;
			isnull = true;
		}
		else
		{
			PyPgType_DatumNew((PyObj) subtype, src, typmod, &d, &isnull);
		}

		if (isnull)
		{
			rob = Py_None;
			Py_INCREF(rob);
		}
		else
		{
			rob = PyPgObject_New(subtype, d);
			if (PyPgType_ShouldFree(subtype))
			{
				Datum fd = d;
				d = 0;
				isnull = true;
				/*
				 * If it fails to pfree, don't try it again in
				 * the catch.
				 */
				pfree(DatumGetPointer(fd));
			}
		}
	}
	PG_CATCH();
	{
		Py_XDECREF(rob);
		rob = NULL;

		if (!isnull && PyPgType_ShouldFree(subtype))
			pfree(DatumGetPointer(d));

		PyErr_SetPgError(false);
	}
	PG_END_TRY();

	Py_XDECREF(typmodin_ob);

	return(rob);
}
Exemplo n.º 8
0
/*
 * XXX: If type methods ever come along, hopefully this will be implemented
 * using a more generalized function.
 */
static PyObj
obj_absolute(PyObj self)
{
	MemoryContext former;
	Oid typoid;
	volatile PyObj rob = NULL;

	if (DB_IS_NOT_READY() || PyPgObjectType_Require(Py_TYPE(self)))
		return(NULL);

	typoid = PyPgType_GetOid(Py_TYPE(self));

	former = CurrentMemoryContext;
	PG_TRY();
	{
		HeapTuple procTuple;
		Datum rd = 0;
		Oid procoid, roid;
		List *qnl;

		qnl = stringToQualifiedNameList("abs");
		procoid = LookupFuncName(qnl, 1, &(typoid), true);
		list_free(qnl);
		if (procoid == InvalidOid)
		{
			PyErr_Format(PyExc_LookupError,
					"no such function named 'abs' for type %u", typoid);
			return(NULL);
		}
		procTuple = SearchSysCache(PROCOID, procoid, 0, 0, 0);
		if (procTuple == NULL)
		{
			PyErr_Format(PyExc_LookupError,
					"no procedure with Oid %u", procoid);
			return(NULL);
		}
		roid = ((Form_pg_proc) GETSTRUCT(procTuple))->prorettype;
		ReleaseSysCache(procTuple);

		rd = OidFunctionCall1(procoid, PyPgObject_GetDatum(self));

		rob = PyPgObject_FromTypeOidAndDatum(roid, rd);
		if (PyPgType_ShouldFree(Py_TYPE(rob)))
		{
			/*
			 * That's our datum...
			 */
			if (PyPgObject_GetDatum(self) != rd)
				pfree(DatumGetPointer(rd));
		}
	}
	PG_CATCH();
	{
		Py_XDECREF(rob);
		PyErr_SetPgError(false);
		return(NULL);
	}
	PG_END_TRY();

	return(rob);
}
Exemplo n.º 9
0
static PyObj
func_call(PyObj self, PyObj args, PyObj kw)
{
	MemoryContext former = CurrentMemoryContext;
	PyObj fn_input, fn_output, input, rob = NULL;
	TupleDesc td;
	FmgrInfo flinfo;
	FunctionCallInfoData fcinfo;
	volatile Datum datum = 0;

	/*
	 * Disallow execution of "anonymous" functions.
	 */
	flinfo.fn_addr = PyPgFunction_GetPGFunction(self);
	flinfo.fn_oid = PyPgFunction_GetOid(self);
	flinfo.fn_retset = PyPgFunction_GetReturnsSet(self);
	if (flinfo.fn_addr == NULL || flinfo.fn_oid == InvalidOid)
	{
		PyErr_SetString(PyExc_TypeError, "internal functions are not directly callable");
		return(NULL);
	}
	if (flinfo.fn_retset)
	{
		PyErr_SetString(PyExc_NotImplementedError,
			"cannot directly execute set returning functions");
		return(NULL);
	}

	fn_input = PyPgFunction_GetInput(self);
	fn_output = PyPgFunction_GetOutput(self);
	if (PyPgTupleDesc_IsPolymorphic(fn_input) ||
		PyPgType_IsPolymorphic(fn_output))
	{
		PyErr_SetString(PyExc_NotImplementedError,
			"cannot directly execute polymorphic functions");
		return(NULL);
	}

	if (PyPgType_GetOid(fn_output) == TRIGGEROID)
	{
		PyErr_SetString(PyExc_NotImplementedError,
			"cannot directly execute TRIGGER returning functions");
		return(NULL);
	}

	/* No access if failed transaction */
	if (DB_IS_NOT_READY())
		return(NULL);

	td = PyPgTupleDesc_GetTupleDesc(fn_input);

	/*
	 * Normalize the parameters.
	 */
	input = PyTuple_FromTupleDescAndParameters(td, args, kw);
	if (input == NULL)
		return(NULL);

	flinfo.fn_nargs = td->natts;
	flinfo.fn_extra = NULL;
	flinfo.fn_mcxt = CurrentMemoryContext;
	flinfo.fn_expr = NULL;
	fcinfo.flinfo = &flinfo;
	fcinfo.context = NULL;
	fcinfo.resultinfo = NULL;
	fcinfo.isnull = false;
	/*
	 * Custom built descriptor; no dropped attributes.
	 */
	fcinfo.nargs = td->natts;

	SPI_push();
	PG_TRY();
	{
		Py_BuildDatumsAndNulls(td,
			PyPgTupleDesc_GetTypesTuple(fn_input),
			input, fcinfo.arg, fcinfo.argnull);

		datum = FunctionCallInvoke(&fcinfo);

		/*
		 * Special casing void to avoid the singleton.
		 */
		if (fcinfo.isnull ||
			PyPgType_GetOid(fn_output) == VOIDOID)
		{
			rob = Py_None;
			Py_INCREF(rob);
		}
		else
		{
			/*
			 * Some functions will return a parameter that its given.
			 * This is problematic if we are going to free the output
			 * after re-allocating as a Postgres.Object.
			 */
			if (PyPgType_ShouldFree(fn_output))
			{
				int i;

				/*
				 * Scan for !typbyval parameters.
				 * When one is found, compare the datum to the result datum.
				 */
				for (i = 0; i < PyTuple_GET_SIZE(input); ++i)
				{
					PyObj param = PyTuple_GET_ITEM(input, i);
					/*
					 * It's tempting to check the types first, but in situations
					 * of functions doing binary compatible coercion, it would be a
					 * mistake.
					 */
					if (PyPgType_ShouldFree(Py_TYPE(param)))
					{
						if (PyPgObject_GetDatum(param) == datum)
						{
							/*
							 * It's the same Datum of an argument,
							 * inc the ref and return the param.
							 */
							if (fn_output == (PyObj) Py_TYPE(param))
							{
								rob = param;
								Py_INCREF(rob);
							}
							else
							{
								/*
								 * It's the same Datum, but a different type.
								 * Make a Copy.
								 */
								rob = PyPgObject_New(fn_output, datum);
							}

							break;
						}
					}
				}

				/*
				 * It's a newly allocated result? (not an argument)
				 */
				if (rob == NULL)
				{
					/*
					 * New result, Datum is copied into the PythonMemoryContext
					 */
					rob = PyPgObject_New(fn_output, datum);
					/*
					 * Cleanup.
					 */
					pfree(DatumGetPointer(datum));
				}
			}
			else
			{
				/* Not pfree'ing typbyval, so no need to check parameters. */
				rob = PyPgObject_New(fn_output, datum);
			}
		}
	}
	PG_CATCH();
	{
		Py_XDECREF(rob);
		rob = NULL;
		PyErr_SetPgError(false);
	}
	PG_END_TRY();
	SPI_pop();

	Py_DECREF(input);

	MemoryContextSwitchTo(former);
	return(rob);
}
Exemplo n.º 10
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);
}