예제 #1
0
/**
 * @brief Convert the current object to a PostbreSQL Datum
 *
 * If the current object is Null, we still return <tt>Datum(0)</tt>, i.e., we
 * return a valid Datum. It is the responsibilty of the caller to separately
 * call isNull().
 *
 * @param inFCInfo The PostgreSQL FunctionCallInfo that was passed to the UDF.
 *     This is necessary for verifying that the top-level AnyType has the
 *     correct type.
 */
inline
Datum
AbstractionLayer::AnyType::getAsDatum(const FunctionCallInfo inFCInfo) {
    consistencyCheck();

    Oid targetTypeID;
    TupleDesc tupleDesc;
    TypeFuncClass funcClass;
    bool exceptionOccurred = false;

    PG_TRY(); {
        // FIXME: get_call_result_type is tagged as expensive in funcapi.c
        // It seems not to be necessary to release the tupleDesc
        // E.g., in plython.c ReleaseTupleDesc() is not called
        funcClass = get_call_result_type(inFCInfo, &targetTypeID, &tupleDesc);
    } PG_CATCH(); {
        exceptionOccurred = true;
    } PG_END_TRY();
    
    if (exceptionOccurred)
        throw std::invalid_argument("An exception occurred while "
            "gathering inormation about the PostgreSQL return type.");

    bool targetIsComposite = (funcClass == TYPEFUNC_COMPOSITE);
    if (targetIsComposite && !isComposite())
        throw std::logic_error("Invalid type conversion requested. "
            "Simple type supplied but PostgreSQL expects composite type.");

    if (!targetIsComposite && isComposite())
        throw std::logic_error("Invalid type conversion requested. "
            "Composite type supplied but PostgreSQL expects simple type.");

    // tupleDesc can be NULL if the return type is not composite
    return getAsDatum(targetTypeID, isComposite(), tupleDesc);
}
/*
 * Generate the .pyi file.
 */
void generateTypeHints(sipSpec *pt, moduleDef *mod, const char *pyiFile)
{
    FILE *fp;

    /* Generate the file. */
    if ((fp = fopen(pyiFile, "w")) == NULL)
        fatal("Unable to create file \"%s\"\n", pyiFile);

    /* Write the header. */
    fprintf(fp,
"# The PEP 484 type hints stub file for the %s module.\n"
"#\n"
"# Generated by SIP %s\n"
        , mod->name
        , sipVersion);

    prCopying(fp, mod, "#");

    fprintf(fp,
"\n"
"\n"
        );

    if (isComposite(mod))
        pyiCompositeModule(pt, mod, fp);
    else
        pyiModule(pt, mod, fp);

    fclose(fp);
}
예제 #3
0
void SegmentedString::advanceAndUpdateLineNumberSlowCase() {
  if (m_currentString.length()) {
    if (m_currentString.getCurrentChar() == '\n' &&
        m_currentString.doNotExcludeLineNumbers()) {
      ++m_currentLine;
      // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet;
      // it does with length() decrement below.
      m_numberOfCharactersConsumedPriorToCurrentLine =
          numberOfCharactersConsumed() + 1;
    }
    m_currentString.decrementLength();
    if (!m_currentString.length())
      advanceSubstring();
    else
      m_currentString.incrementAndGetCurrentChar();  // Only need the ++
  } else if (!isComposite()) {
    m_currentString.clear();
    m_empty = true;
    m_fastPathFlags = NoFastPath;
    m_advanceFunc = &SegmentedString::advanceEmpty;
    m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
  }

  m_currentChar =
      m_currentString.length() ? m_currentString.getCurrentChar() : 0;
}
예제 #4
0
void SegmentedString::advanceAndUpdateLineNumberSlowCase()
{
    if (m_pushedChar1) {
        m_pushedChar1 = m_pushedChar2;
        m_pushedChar2 = 0;

        if (m_pushedChar1) {
            m_currentChar = m_pushedChar1;
            return;
        }

        updateAdvanceFunctionPointers();
    } else if (m_currentString.m_length) {
        if (m_currentString.getCurrentChar() == '\n' && m_currentString.doNotExcludeLineNumbers()) {
            ++m_currentLine;
            // Plus 1 because numberOfCharactersConsumed value hasn't incremented yet; it does with m_length decrement below.
            m_numberOfCharactersConsumedPriorToCurrentLine = numberOfCharactersConsumed() + 1;
        }
        if (--m_currentString.m_length == 0)
            advanceSubstring();
        else
            m_currentString.incrementAndGetCurrentChar(); // Only need the ++
    } else if (!isComposite()) {
        m_currentString.clear();
        m_empty = true;
        m_fastPathFlags = NoFastPath;
        m_advanceFunc = &SegmentedString::advanceEmpty;
        m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    }

    m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
}
예제 #5
0
void SegmentedString::setExcludeLineNumbers() {
  m_currentString.setExcludeLineNumbers();
  if (isComposite()) {
    Deque<SegmentedSubstring>::iterator it = m_substrings.begin();
    Deque<SegmentedSubstring>::iterator e = m_substrings.end();
    for (; it != e; ++it)
      it->setExcludeLineNumbers();
  }
}
예제 #6
0
unsigned SegmentedString::length() const {
  unsigned length = m_currentString.length();
  if (isComposite()) {
    Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
    Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
    for (; it != e; ++it)
      length += it->length();
  }
  return length;
}
예제 #7
0
String SegmentedString::toString() const {
  StringBuilder result;
  m_currentString.appendTo(result);
  if (isComposite()) {
    Deque<SegmentedSubstring>::const_iterator it = m_substrings.begin();
    Deque<SegmentedSubstring>::const_iterator e = m_substrings.end();
    for (; it != e; ++it)
      it->appendTo(result);
  }
  return result.toString();
}
예제 #8
0
void SegmentedString::advanceSlowCase() {
  if (m_currentString.length()) {
    m_currentString.decrementLength();
    if (!m_currentString.length())
      advanceSubstring();
  } else if (!isComposite()) {
    m_currentString.clear();
    m_empty = true;
    m_fastPathFlags = NoFastPath;
    m_advanceFunc = &SegmentedString::advanceEmpty;
    m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
  }
  m_currentChar =
      m_currentString.length() ? m_currentString.getCurrentChar() : 0;
}
예제 #9
0
/**
 * @brief Return the n-th element from a composite value
 *
 * To the user, AnyType is a fully recursive type: Each AnyType object can be a
 * composite object and be composed of a number of other AnyType objects.
 * On top of the C++ abstraction layer, function have a single-top level
 * AnyType object as parameter.
 */
inline
AbstractionLayer::AnyType
AbstractionLayer::AnyType::operator[](uint16_t inID) const {
    consistencyCheck();

    if (isNull())
        throw std::invalid_argument("Unexpected Null value in function "
            "argument.");
    if (!isComposite())
        throw std::invalid_argument("Invalid type conversion requested. "
            "Expected composite type but got simple type.");
    
    if (mContent == ReturnComposite)
        return mChildren[inID];

    Oid typeID = 0;
    bool isMutable = false;
    Datum datum = 0;
    bool isTuple = false;
    HeapTupleHeader pgTuple = NULL;

    try {
        if (mContent == FunctionComposite) {
            if (inID >= size_t(PG_NARGS()))
                throw std::out_of_range("Access behind end of argument list");
            
            if (PG_ARGISNULL(inID))
                return AnyType();
                    
            backendGetTypeIDForFunctionArg(inID, typeID, isMutable);
            datum = PG_GETARG_DATUM(inID);
        } else if (mContent == NativeComposite)
            backendGetTypeIDAndDatumForTupleElement(inID, typeID, datum);
        
        if (typeID == InvalidOid)
            throw std::invalid_argument("Backend returned invalid type ID.");
        
        backendGetIsCompositeTypeAndHeapTupleHeader(typeID, datum, isTuple,
            pgTuple);
    } catch (PGException &e) {
        throw std::invalid_argument("An exception occurred while "
            "gathering information about PostgreSQL function arguments.");
    }

    return isTuple ?
        AnyType(pgTuple, datum, typeID) :
        AnyType(datum, typeID, isMutable);
}
예제 #10
0
void CCPACSMaterial::ReadCPACS(TixiDocumentHandle tixiHandle, const std::string &materialXPath)
{
    Cleanup();
    
    // check path
    if ( tixiCheckElement(tixiHandle, materialXPath.c_str()) != SUCCESS) {
        LOG(ERROR) << "Material definition" << materialXPath << " not found in CPACS file!" << std::endl;
        return;
    }
    
    // test whether composite or normal material
    std::string tempstring = materialXPath + "/materialUID";
    char * matUID = NULL;
    if (tixiGetTextElement(tixiHandle, tempstring.c_str(), &matUID) == SUCCESS){
        uid = matUID;
        is_composite = false;
    }
    else if (tixiGetTextElement(tixiHandle, std::string(materialXPath + "/compositeUID").c_str(), &matUID) == SUCCESS){
        uid = matUID;
        is_composite = true;
    }
    else {
        throw CTiglError("Neither Material UID nor Composite UID  specified in " + materialXPath, TIGL_ERROR);
    }
    
    // get thickness (not mandatory)
    tempstring = materialXPath + "/thickness";
    if (tixiCheckElement(tixiHandle, tempstring.c_str())== SUCCESS) {
       if (tixiGetDoubleElement(tixiHandle, tempstring.c_str(), &thickness) != SUCCESS) {
           LOG(ERROR) << "Invalid material thickness in " << materialXPath;
       }
    }
    else if (tixiCheckElement(tixiHandle, std::string(materialXPath + "/thicknessScaling").c_str())== SUCCESS) {
       if (tixiGetDoubleElement(tixiHandle, std::string(materialXPath + "/thicknessScaling").c_str(), &thicknessScaling) != SUCCESS) {
           LOG(ERROR) << "Invalid composite thickness scaling in " << materialXPath;
       }
    }
    else {
        if (!isComposite()) {
            LOG(INFO) << "Thickness of Material " << materialXPath << " not set.";
        }
        else {
            LOG(INFO) << "Thickness scaling of Composite Material " << materialXPath << " not set.";
        }
    }
    
    isvalid = true;
}
예제 #11
0
파일: isprime2.cpp 프로젝트: Neverous/team
inline bool isPrime(long long unsigned int &number)
{
	if(number < 4)
		return true;

	if(number % 2 == 0)
		return false;

	long long unsigned int base;
	for(int t = 0; t < TRIES; ++ t)
	{
		base = random(2, number - 2);
		if(isComposite(base, number))
			return false;
	}

	return true;
}
예제 #12
0
void SegmentedString::advanceSubstring()
{
    if (isComposite()) {
        m_numberOfCharactersConsumedPriorToCurrentString += m_currentString.numberOfCharactersConsumed();
        m_currentString = m_substrings.takeFirst();
        // If we've previously consumed some characters of the non-current
        // string, we now account for those characters as part of the current
        // string, not as part of "prior to current string."
        m_numberOfCharactersConsumedPriorToCurrentString -= m_currentString.numberOfCharactersConsumed();
        updateAdvanceFunctionPointers();
    } else {
        m_currentString.clear();
        m_empty = true;
        m_fastPathFlags = NoFastPath;
        m_advanceFunc = &SegmentedString::advanceEmpty;
        m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    }
}
예제 #13
0
inline
T
AnyType::getAs() const {
    consistencyCheck();

    if (isNull())
        throw std::invalid_argument("Invalid type conversion. "
                                    "Null where not expected.");

    if (isComposite())
        throw std::invalid_argument("Invalid type conversion. "
                                    "Composite type where not expected.");

    // Verify type OID
    if (TypeTraits<T>::oid != InvalidOid && mTypeID != TypeTraits<T>::oid) {
        std::stringstream errorMsg;
        errorMsg << "Invalid type conversion. Expected type ID "
                 << TypeTraits<T>::oid;
        if (mSysInfo)
            errorMsg << " ('"
                     << mSysInfo->typeInformation(TypeTraits<T>::oid)->getName()
                     << "')";
        errorMsg << " but got " << mTypeID;
        if (mSysInfo)
            errorMsg << " ('"
                     << mSysInfo->typeInformation(mTypeID)->getName() << "')";
        errorMsg << '.';
        throw std::invalid_argument(errorMsg.str());
    }

    // Verify type name
    if (TypeTraits<T>::typeName() &&
            std::strncmp(mTypeName, TypeTraits<T>::typeName(), NAMEDATALEN)) {

        std::stringstream errorMsg;
        errorMsg << "Invalid type conversion. Expected type '"
                 << TypeTraits<T>::typeName() << "' but backend type name is '"
                 << mTypeName << "' (ID " << mTypeID << ").";
    }

    bool needMutableClone = (TypeTraits<T>::isMutable && !mIsMutable);
    return TypeTraits<T>::toCXXType(mDatum, needMutableClone, mSysInfo);
}
예제 #14
0
T AbstractionLayer::AnyType::getAs() const {
    consistencyCheck();
    
    if (isNull())
        throw std::invalid_argument("Invalid type conversion requested. Got "
            "Null from backend.");
    
    if (isComposite())
        throw std::invalid_argument("Invalid type conversion requested. "
            "Expected simple or array type but got composite type from "
            "backend.");

    if (mTypeID != TypeTraits<T>::oid)
        throw std::invalid_argument(
            "Invalid type conversion requested. PostgreSQL type does not match "
                "C++ type.");
    
    bool needMutableClone = (TypeTraits<T>::isMutable && !mIsMutable);
    
    return TypeTraits<T>::toCXXType(mDatum, needMutableClone);
}
예제 #15
0
void SegmentedString::advanceSlowCase()
{
    if (m_pushedChar1) {
        m_pushedChar1 = m_pushedChar2;
        m_pushedChar2 = 0;

        if (m_pushedChar1) {
            m_currentChar = m_pushedChar1;
            return;
        }

        updateAdvanceFunctionPointers();
    } else if (m_currentString.m_length) {
        if (--m_currentString.m_length == 0)
            advanceSubstring();
    } else if (!isComposite()) {
        m_currentString.clear();
        m_empty = true;
        m_fastPathFlags = NoFastPath;
        m_advanceFunc = &SegmentedString::advanceEmpty;
        m_advanceAndUpdateLineNumberFunc = &SegmentedString::advanceEmpty;
    }
    m_currentChar = m_currentString.m_length ? m_currentString.getCurrentChar() : 0;
}
예제 #16
0
 /**
  * @brief A built-in module type is part of nmlib, and not created by the user.
  */
 bool isBuiltin() const {
     return !isComposite();    //subject to change (some builtins may become composites in the future
 }
예제 #17
0
/**
 * @brief Return a PostgreSQL Datum representing the current object
 *
 * If the current object is Null, we still return <tt>Datum(0)</tt>, i.e., we
 * return a valid Datum. It is the responsibilty of the caller to separately
 * call isNull().
 *
 * The only *conversion* taking place in this function is *combining* Datums
 * into a tuple. At this place, we do not have to worry any more about retaining
 * memory.
 *
 * @param inFnCallInfo The PostgreSQL FunctionCallInfo that was passed to the
 *     UDF. For polymorphic functions or functions that return RECORD, the
 *     function-call information (specifically, the expression parse tree)
 *     is necessary to dynamically resolve type information.
 * @param inTargetTypeID PostgreSQL OID of the target type to convert to. If
 *     omitted the target type is the return type of the function specified by
 *     \c inFnCallInfo.
 *
 * @see getAsDatum(const FunctionCallInfo)
 */
inline
Datum
AnyType::getAsDatum(FunctionCallInfo inFnCallInfo,
                    Oid inTargetTypeID) const {

    consistencyCheck();

    // The default value to return in case of Null is 0. Note, however, that
    // 0 can also be a perfectly valid (non-null) Datum. It is the caller's
    // responsibility to call isNull() separately.
    if (isNull())
        return 0;

    // Note: mSysInfo is NULL if this object was not an argument from the
    // backend.
    SystemInformation* sysInfo = SystemInformation::get(inFnCallInfo);
    FunctionInformation* funcInfo = sysInfo
                                    ->functionInformation(inFnCallInfo->flinfo->fn_oid);
    TupleDesc targetTupleDesc;
    if (inTargetTypeID == InvalidOid) {
        inTargetTypeID = funcInfo->getReturnType(inFnCallInfo);

        // If inTargetTypeID is \c RECORDOID, the tuple description needs to be
        // derived from the function call
        targetTupleDesc = funcInfo->getReturnTupleDesc(inFnCallInfo);
    } else {
        // If we are here, we should not see inTargetTypeID == RECORDOID because
        // that should only happen for the first non-recursive call of
        // getAsDatum where inTargetTypeID == InvalidOid by default.
        // If it would happen, then the following would return NULL and an
        // exception would be raised a few line below. So no need to add a check
        // here.
        targetTupleDesc = sysInfo->typeInformation(inTargetTypeID)
                          ->getTupleDesc();
    }

    bool targetIsComposite = targetTupleDesc != NULL;
    Datum returnValue = mDatum;

    if (targetIsComposite && !isComposite())
        throw std::runtime_error("Invalid type conversion. "
                                 "Simple type supplied but backend expects composite type.");

    if (!targetIsComposite && isComposite())
        throw std::runtime_error("Invalid type conversion. "
                                 "Composite type supplied but backend expects simple type.");

    if (targetIsComposite) {
        if (static_cast<size_t>(targetTupleDesc->natts) < mChildren.size())
            throw std::runtime_error("Invalid type conversion. "
                                     "Internal composite type has more elements than backend "
                                     "composite type.");

        std::vector<Datum> values;
        std::vector<char> nulls;

        for (uint16_t pos = 0; pos < mChildren.size(); ++pos) {
            Oid targetTypeID = targetTupleDesc->attrs[pos]->atttypid;

            values.push_back(mChildren[pos].getAsDatum(inFnCallInfo,
                             targetTypeID));
            nulls.push_back(mChildren[pos].isNull());
        }
        // All elements that have not been initialized will be set to Null
        for (uint16_t pos = mChildren.size();
                pos < static_cast<size_t>(targetTupleDesc->natts);
                ++pos) {

            values.push_back(Datum(0));
            nulls.push_back(true);
        }

        HeapTuple heapTuple = madlib_heap_form_tuple(targetTupleDesc,
                              &values[0], reinterpret_cast<bool*>(&nulls[0]));
        // BACKEND: HeapTupleGetDatum is a macro that will not cause an
        // exception
        returnValue = HeapTupleGetDatum(heapTuple);
    } else { /* if (!targetIsComposite) */
        if (mTypeID != InvalidOid && inTargetTypeID != mTypeID) {
            std::stringstream errorMsg;
            errorMsg << "Invalid type conversion. "
                     "Backend expects type ID " << inTargetTypeID << " ('"
                     << sysInfo->typeInformation(inTargetTypeID)->getName() << "') "
                     "but supplied type ID is " << mTypeID << + " ('"
                     << sysInfo->typeInformation(mTypeID)->getName() << "').";
            throw std::invalid_argument(errorMsg.str());
        }

        if (mTypeName && std::strncmp(mTypeName,
                                      sysInfo->typeInformation(inTargetTypeID)->getName(),
                                      NAMEDATALEN)) {

            std::stringstream errorMsg;
            errorMsg << "Invalid type conversion. Backend expects type '"
                     << sysInfo->typeInformation(inTargetTypeID)->getName() <<
                     "' (ID " << inTargetTypeID << ") but internal type name is '"
                     << mTypeName << "'.";
            throw std::invalid_argument(errorMsg.str());
        }
    }

    return returnValue;
}
예제 #18
0
/**
 * @brief Return the n-th element from a composite value
 *
 * To the user, AnyType is a fully recursive type: Each AnyType object can be a
 * composite object and be composed of a number of other AnyType objects.
 * Function written using the C++ abstraction layer have a single logical
 * argument of type AnyType.
 */
inline
AnyType
AnyType::operator[](uint16_t inID) const {
    consistencyCheck();

    if (isNull()) {
        // Handle case mContent == NULL
        throw std::invalid_argument("Invalid type conversion. "
                                    "Null where not expected.");
    }
    if (!isComposite()) {
        // Handle case mContent == Scalar
        throw std::invalid_argument("Invalid type conversion. "
                                    "Composite type where not expected.");
    }

    if (mContent == ReturnComposite)
        return mChildren[inID];

    // It holds now that mContent is either FunctionComposite or NativeComposite
    // In this case, it is guaranteed that fcinfo != NULL
    Oid typeID = 0;
    bool isMutable = false;
    Datum datum = 0;

    if (mContent == FunctionComposite) {
        // This AnyType object represents to composite value consisting of all
        // function arguments

        if (inID >= size_t(PG_NARGS()))
            throw std::out_of_range("Invalid type conversion. Access behind "
                                    "end of argument list.");

        if (PG_ARGISNULL(inID))
            return AnyType();

        typeID = mSysInfo->functionInformation(fcinfo->flinfo->fn_oid)
                 ->getArgumentType(inID, fcinfo->flinfo);
        if (inID == 0) {
            // If we are called as an aggregate function, the first argument is
            // the transition state. In that case, we are free to modify the
            // data. In fact, for performance reasons, we *should* even do all
            // modifications in-place. In all other cases, directly modifying
            // memory is dangerous.
            // See warning at:
            // http://www.postgresql.org/docs/current/static/xfunc-c.html#XFUNC-C-BASETYPE

            // BACKEND: AggCheckCallContext currently will never raise an
            // exception
            isMutable = AggCheckCallContext(fcinfo, NULL);
        }
        datum = PG_GETARG_DATUM(inID);
    } else { /* if (mContent == NativeComposite) */
        // This AnyType objects represents a tuple that was passed from the
        // backend

        TupleDesc tupdesc = mSysInfo
                            ->typeInformation(HeapTupleHeaderGetTypeId(mTupleHeader))
                            ->getTupleDesc(HeapTupleHeaderGetTypMod(mTupleHeader));

        if (inID >= tupdesc->natts)
            throw std::out_of_range("Invalid type conversion. Access behind "
                                    "end of composite object.");

        typeID = tupdesc->attrs[inID]->atttypid;
        bool isNull = false;
        datum = madlib_GetAttributeByNum(mTupleHeader, inID, &isNull);
        if (isNull)
            return AnyType();
    }

    if (typeID == InvalidOid)
        throw std::invalid_argument("Backend returned invalid type ID.");

    return mSysInfo->typeInformation(typeID)->isCompositeType()
           ? AnyType(mSysInfo, madlib_DatumGetHeapTupleHeader(datum), datum,
                     typeID)
           : AnyType(mSysInfo, datum, typeID, isMutable);
}
예제 #19
0
void SegmentedString::advanceEmpty()
{
    ASSERT(!m_currentString.m_length && !isComposite());
    m_currentChar = 0;
}
예제 #20
0
inline CubitBoolean CompositeTool::
  isComposite( const BasicTopologyEntity* bte_ptr ) const
{
  return bte_ptr ? isComposite(bte_ptr->get_geometry_entity_ptr()) : CUBIT_FALSE;
}
예제 #21
0
/**
 * @brief Return a PostgreSQL Datum representing the current object
 *
 * The only *conversion* taking place in this function is *combining* Datums
 * into a tuple. At this place, we do not have to worry any more about retaining
 * memory.
 *
 * @param inTargetTypeID PostgreSQL OID of the target type to convert to
 * @param inTargetIsComposite Whether the target type is composite.
 *     \c indeterminate if unknown.
 * @param inTargetTupleDesc If target type is known to be composite, then
 *     (optionally) the PostgreSQL TupleDesc. NULL is always a valid argument.
 *
 * @see getAsDatum(const FunctionCallInfo)
 */
inline
Datum
AbstractionLayer::AnyType::getAsDatum(Oid inTargetTypeID,
    boost::tribool inTargetIsComposite, TupleDesc inTargetTupleDesc) const {
    
    consistencyCheck();

    // The default value to return in case of Null is 0. Note, however, that
    // 0 can also be a perfectly valid (non-null) Datum. It is the caller's
    // responsibility to call isNull() separately.
    if (isNull())
        return 0;

    try {
        bool exceptionOccurred = false;
        TupleHandle tupleHandle(inTargetTupleDesc);
        
        if (boost::indeterminate(inTargetIsComposite)) {
            inTargetIsComposite = isRowTypeInCache(inTargetTypeID);
            backendGetIsCompositeTypeAndTupleHandle(inTargetTypeID,
                inTargetIsComposite, tupleHandle);
        }
        
        if (inTargetIsComposite && !isComposite())
            throw std::runtime_error("Invalid type conversion requested. "
                "Simple type supplied but PostgreSQL expects composite type.");

        if (!inTargetIsComposite && isComposite())
            throw std::runtime_error("Invalid type conversion requested. "
                "Composite type supplied but PostgreSQL expects simple type.");
        
        madlib_assert(inTargetIsComposite == (tupleHandle.desc != NULL),
            MADLIB_DEFAULT_EXCEPTION);
        
        if (inTargetIsComposite) {
            if (static_cast<size_t>(tupleHandle.desc->natts) < mChildren.size())
                throw std::runtime_error("Invalid type conversion requested. "
                    "Internal composite type has more elements than PostgreSQL "
                    "composite type.");

            std::vector<Datum> values;
            std::vector<char> nulls;

            for (uint16_t pos = 0; pos < mChildren.size(); ++pos) {
                Oid targetTypeID = tupleHandle.desc->attrs[pos]->atttypid;
                                    
                values.push_back(mChildren[pos].getAsDatum(targetTypeID));
                nulls.push_back(mChildren[pos].isNull());
            }
            // All elements that have not been initialized will be set to Null
            for (uint16_t pos = mChildren.size();
                pos < static_cast<size_t>(tupleHandle.desc->natts);
                ++pos) {
                
                values.push_back(Datum(0));
                nulls.push_back(true);
            }
            
            Datum returnValue;
            PG_TRY(); {
                HeapTuple heapTuple = heap_form_tuple(tupleHandle.desc,
                    &values[0], reinterpret_cast<bool*>(&nulls[0]));
                
                returnValue = HeapTupleGetDatum(heapTuple);
            } PG_CATCH(); {
                exceptionOccurred = true;
            } PG_END_TRY();
            
            if (exceptionOccurred)
                throw PGException();
            
            return returnValue;
        }
    } catch (PGException &e) {
        throw std::invalid_argument("An exception occurred while "
            "gathering inormation about the PostgreSQL return type.");
    }
        
    if (inTargetTypeID != mTypeID)
        throw std::invalid_argument("Invalid type conversion requested. "
            "C++ type and PostgreSQL return type do not match.");
    
    return mDatum;
}