Exemple #1
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);
}
Exemple #2
0
/*
 * array_from_elements - classmethod to build an array
 */
static PyObj
array_from_elements(PyObj self, PyObj args, PyObj kw)
{
	static char *kwlist[] = {"elements", "dimensions", "lowerbounds", NULL};
	PyObj rob = NULL, iter, listob, dims_ob = NULL, lbs_ob = NULL;
	int dims[MAXDIM];
	int lbs[MAXDIM] = {1, 0,};
	int ndims = 1, nelems;
	Py_ssize_t i;
	ArrayType *rat = NULL;

	if (!PyArg_ParseTupleAndKeywords(args, kw, "O|OO:from_elements",
		kwlist, &iter, &dims_ob, &lbs_ob))
	{
		return(NULL);
	}

	listob = Py_Call((PyObj) &PyList_Type, iter);
	if (listob == NULL)
		return(NULL);
	Assert(PyList_CheckExact(listob));

	/*
	 * Convert the dimensions keyword into a tuple and extract the values
	 * into the dims[] array.
	 */
	if (dims_ob != NULL && dims_ob != Py_None)
	{
		PyObj tdims_ob;

		tdims_ob = Py_Call((PyObj) &PyTuple_Type, dims_ob);
		if (tdims_ob == NULL)
			goto fail;

		ndims = PyTuple_GET_SIZE(tdims_ob);
		if (ndims > MAXDIM)
		{
			Py_DECREF(tdims_ob);
			PyErr_Format(PyExc_ValueError, "too many dimensions (%d) for array",
							ndims);
			goto fail;
		}

		if (ndims > 0)
		{
			for (i = 0; i < ndims; ++i)
			{
				dims[i] = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tdims_ob, i),
													NULL);
				if (PyErr_Occurred())
				{
					Py_DECREF(tdims_ob);
					goto fail;
				}
			}
		}
		else
			dims[0] = 0;

		Py_DECREF(tdims_ob);
	}
	else
	{
		dims[0] = PyList_GET_SIZE(listob);
		if (dims[0] == 0)
			ndims = 0;
	}

	nelems = dims[0];
	if (ndims > 1)
	{
		for (i = 1; i < ndims; ++i)
			nelems = nelems * dims[i];
	}

	if (nelems != PyList_GET_SIZE(listob))
	{
		PyErr_Format(PyExc_ValueError,
			"dimension capacity (%d) does not accommodate the given elements (%d)",
			nelems, PyList_GET_SIZE(listob));
		goto fail;
	}

	if (lbs_ob != NULL && lbs_ob != Py_None)
	{
		PyObj tlbs_ob;

		tlbs_ob = Py_Call((PyObj) &PyTuple_Type, lbs_ob);
		if (tlbs_ob == NULL)
			goto fail;

		if (PyTuple_GET_SIZE(tlbs_ob) > MAXDIM)
		{
			Py_DECREF(tlbs_ob);
			PyErr_SetString(PyExc_ValueError, "too many dimensions for array");
			goto fail;
		}

		if (PyTuple_GET_SIZE(tlbs_ob) != ndims)
		{
			Py_DECREF(tlbs_ob);
			PyErr_Format(PyExc_ValueError, "number of lower bounds (%d) is "
				"inconsistent with dimensions (%d)",
				PyTuple_GET_SIZE(tlbs_ob), ndims);
			goto fail;
		}

		for (i = 0; i < PyTuple_GET_SIZE(tlbs_ob); ++i)
		{
			lbs[i] = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tlbs_ob, i),
												NULL);
			if (PyErr_Occurred())
			{
				Py_DECREF(tlbs_ob);
				goto fail;
			}
		}

		Py_DECREF(tlbs_ob);
	}
	else
	{
		/*
		 * No lower bounds specified, fill in with 1's.
		 */
		for (i = 0; i < ndims; ++i)
		{
			lbs[i] = 1;
		}
	}

	rat = array_from_list_and_info(
		PyPgType_GetElementType(self),
		listob, -1, ndims, dims, lbs);
	Py_DECREF(listob);

	if (rat != NULL)
	{
		rob = PyPgObject_New(self, PointerGetDatum(rat));
		pfree(rat);
	}

	return(rob);
fail:
	Py_XDECREF(listob);
	return(NULL);
}
Exemple #3
0
/*
 * Array.get_element(indexes) - Get an element from the array.
 *
 * This uses Python sequence semantics(zero-based indexes, IndexError's).
 */
static PyObj
array_get_element(PyObj self, PyObj indexes_ob)
{
	PyObj tup, element_type, rob = NULL;
	PyPgTypeInfo atypinfo, typinfo;
	ArrayType *at;
	int i, nindexes, indexes[MAXDIM] = {0,};

	/*
	 * Convert the indexes_ob into a tuple and extract the values
	 * into the indexes[] array. Do any necessary checks along the way.
	 */
	tup = Py_Call((PyObj) &PyTuple_Type, indexes_ob);
	if (tup == NULL)
		return(NULL);

	nindexes = (int) PyTuple_GET_SIZE(tup);

	if (!(nindexes > 0))
	{
		Py_DECREF(tup);
		PyErr_SetString(PyExc_ValueError, "empty index tuple");
		return(NULL);
	}

	at = DatumGetArrayTypeP(PyPgObject_GetDatum(self));
	Assert(at != NULL);

	if (nindexes != ARR_NDIM(at))
	{
		Py_DECREF(tup);
		if (ARR_NDIM(at) == 0)
			PyErr_SetString(PyExc_IndexError, "no elements in array");
		else
			PyErr_Format(PyExc_ValueError, "element access requires exactly %d indexes, given %d",
				ARR_NDIM(at), nindexes);
		return(NULL);
	}

	for (i = 0; i < nindexes; ++i)
	{
		int index;
		index = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, i),
											NULL);
		if (PyErr_Occurred())
		{
			Py_DECREF(tup);
			return(NULL);
		}

		/*
		 * Adjust for backwards based access. (feature of get_element)
		 */
		if (index < 0)
			indexes[i] = index + ARR_DIMS(at)[i];
		else
			indexes[i] = index;

		if (indexes[i] >= ARR_DIMS(at)[i] || indexes[i] < 0)
		{
			PyErr_Format(PyExc_IndexError, "index %d out of range %d for axis %d",
				index, ARR_DIMS(at)[0], i);
			Py_DECREF(tup);
			return(NULL);
		}

		/*
		 * Adjust by the lowerbounds..
		 */
		indexes[i] = indexes[i] + ARR_LBOUND(at)[i];
	}

	Py_DECREF(tup);

	atypinfo = PyPgTypeInfo(Py_TYPE(self));
	element_type = PyPgType_GetElementType(Py_TYPE(self));
	typinfo = PyPgTypeInfo(element_type);

	PG_TRY();
	{
		Datum rd;
		bool isnull = false;

		rd = array_ref(at, nindexes, indexes, atypinfo->typlen,
			typinfo->typlen, typinfo->typbyval, typinfo->typalign, &isnull);

		if (isnull)
		{
			rob = Py_None;
			Py_INCREF(rob);
		}
		else
		{
			/*
			 * It points into the array structure, so there's no need to free.
			 */
			rob = PyPgObject_New(element_type, rd);
		}
	}
	PG_CATCH();
	{
		PyErr_SetPgError(false);
	}
	PG_END_TRY();

	return(rob);
}
Exemple #4
0
static PyObj
array_sql_get_element(PyObj self, PyObj indexes_ob)
{
	PyObj tup, element_type, rob = NULL;
	PyPgTypeInfo atypinfo, typinfo;
	ArrayType *at;
	int i, nindexes, indexes[MAXDIM] = {0,};

	/*
	 * Convert the dimensions keyword into a tuple and extract the values
	 * into the dims[] array.
	 */

	tup = Py_Call((PyObj) &PyTuple_Type, indexes_ob);
	if (tup == NULL)
		return(NULL);

	at = DatumGetArrayTypeP(PyPgObject_GetDatum(self));
	Assert(at != NULL);

	nindexes = (int) PyTuple_GET_SIZE(tup);
	if (nindexes != ARR_NDIM(at))
	{
		Py_DECREF(tup);
		Py_INCREF(Py_None);
		return(Py_None);
	}

	for (i = 0; i < nindexes; ++i)
	{
		indexes[i] = (int) PyNumber_AsSsize_t(PyTuple_GET_ITEM(tup, i),
											NULL);
		if (PyErr_Occurred())
		{
			Py_DECREF(tup);
			return(NULL);
		}
	}

	Py_DECREF(tup);

	atypinfo = PyPgTypeInfo(Py_TYPE(self));
	element_type = PyPgType_GetElementType(Py_TYPE(self));
	typinfo = PyPgTypeInfo(element_type);

	/*
	 * Single dimenion array? Get an element.
	 */
	PG_TRY();
	{
		Datum rd;
		bool isnull = false;

		rd = array_ref(at, nindexes, indexes, atypinfo->typlen,
			typinfo->typlen, typinfo->typbyval, typinfo->typalign, &isnull);

		if (isnull)
		{
			rob = Py_None;
			Py_INCREF(rob);
		}
		else
		{
			/*
			 * It points into the array structure, so there's no need to free.
			 */
			rob = PyPgObject_New(element_type, rd);
		}
	}
	PG_CATCH();
	{
		PyErr_SetPgError(false);
	}
	PG_END_TRY();

	return(rob);
}