blob: db0d477dfe4c96e9613b96c5119f4e1a4b6fbf43 [file] [log] [blame]
/* ----------------------------------------------------------------------- *//**
*
* @file ArrayHandle_impl.hpp
*
*//* ----------------------------------------------------------------------- */
#ifndef MADLIB_POSTGRES_ARRAYHANDLE_IMPL_HPP
#define MADLIB_POSTGRES_ARRAYHANDLE_IMPL_HPP
namespace madlib {
namespace dbconnector {
namespace postgres {
template <typename T>
inline
ArrayHandle<T>::ArrayHandle(ArrayType *inArray): mArray(inArray) {
if (inArray == NULL) {
mData = NULL;
mNumElems = -1;
mElemLen = -1;
mElemByVal = false;
mElemAlign = -1;
} else {
madlib_get_typlenbyvalalign(ARR_ELEMTYPE(inArray),
&mElemLen,
&mElemByVal,
&mElemAlign);
if (mElemByVal) {
mData = reinterpret_cast<T*>(ARR_DATA_PTR(inArray));
mNumElems = static_cast<int>(this->size());
} else {
// FIXME deallocate memory for datum_ptr and mData!
Datum *datum_ptr;
deconstruct_array(inArray,
ARR_ELEMTYPE(inArray),
mElemLen,
mElemByVal,
mElemAlign,
&datum_ptr,
NULL,
&mNumElems);
mData = new T[mNumElems];
for (int i = 0; i < mNumElems; i ++) {
varlena *detoast_ptr = PG_DETOAST_DATUM(datum_ptr[i]);
char *index_ptr = reinterpret_cast<char*>(&detoast_ptr);
mData[i] = *(reinterpret_cast<T*>(index_ptr));
}
}
}
}
template <typename T>
inline
const T*
ArrayHandle<T>::ptr() const {
if (mArray == NULL) { return NULL; }
if (mElemByVal) {
return reinterpret_cast<T*>(ARR_DATA_PTR(mArray));
} else {
return reinterpret_cast<T*>(mData);
}
}
template <typename T>
inline
size_t
ArrayHandle<T>::size() const {
madlib_assert(ptr() != NULL, std::runtime_error(
"Attempt to getting size() of a NULL array detected."));
// An empty array has dimensionality 0.
size_t arraySize = ARR_NDIM(mArray) ? 1 : 0;
for (int i = 0; i < ARR_NDIM(mArray); ++i) {
arraySize *= ARR_DIMS(mArray)[i];
}
return arraySize;
}
template <typename T>
inline
size_t
ArrayHandle<T>::dims() const {
madlib_assert(ptr() != NULL, std::runtime_error(
"Attempt to getting dims() of a NULL array detected."));
return ARR_NDIM(mArray);
}
template <typename T>
inline
size_t
ArrayHandle<T>::sizeOfDim(size_t inDim) const {
if (inDim >= dims()) {
throw std::invalid_argument("Invalid dimension.");
}
return ARR_DIMS(mArray)[inDim];
}
template <typename T>
inline
const ArrayType*
ArrayHandle<T>::array() const {
return mArray;
}
template <typename T>
inline
const T&
ArrayHandle<T>::operator[](size_t inIndex) const {
madlib_assert(ptr() != NULL, std::runtime_error(
"Indexing (operator[]) into a NULL array detected."));
madlib_assert(inIndex < size(), std::runtime_error(
"Out-of-bounds array access detected."));
return ptr()[inIndex];
}
template <typename T>
inline
T*
MutableArrayHandle<T>::ptr() {
return const_cast<T*>(static_cast<const ArrayHandle<T>*>(this)->ptr());
}
template <typename T>
inline
ArrayType*
MutableArrayHandle<T>::array() {
return const_cast< ArrayType* >(Base::mArray);
}
template <typename T>
inline
T&
MutableArrayHandle<T>::operator[](size_t inIndex) {
return const_cast<T&>(
static_cast<const ArrayHandle<T>*>(this)->operator[](inIndex)
);
}
} // namespace postgres
} // namespace dbconnector
} // namespace madlib
#endif // defined(MADLIB_POSTGRES_ARRAYHANDLE_IMPL_HPP)