/*
Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef NdbRecAttr_H
#define NdbRecAttr_H
#include "NdbDictionary.hpp"
#include "Ndb.hpp"
class NdbOperation;
/**
* @class NdbRecAttr
* @brief Contains value of an attribute.
*
* NdbRecAttr objects are used to store the attribute value
* after retrieving the value from the NDB Cluster using the method
* NdbOperation::getValue. The objects are allocated by the NDB API.
* An example application program follows:
*
* @code
* MyRecAttr = MyOperation->getValue("ATTR2", NULL);
* if (MyRecAttr == NULL) goto error;
*
* if (MyTransaction->execute(Commit) == -1) goto error;
*
* ndbout << MyRecAttr->u_32_value();
* @endcode
* For more examples, see
* @ref ndbapi_simple.cpp.
*
* @note The NdbRecAttr object is instantiated with its value when
* NdbTransaction::execute is called. Before this, the value is
* undefined. (NdbRecAttr::isNULL can be used to check
* if the value is defined or not.)
* This means that an NdbRecAttr object only has valid information
* between the time of calling NdbTransaction::execute and
* the time of Ndb::closeTransaction.
* The value of the null indicator is -1 until the
* NdbTransaction::execute method have been called.
*
* For simple types, there are methods which directly getting the value
* from the NdbRecAttr object.
*
* To get a reference to the value, there are two methods:
* NdbRecAttr::aRef (memory is released by NDB API) and
* NdbRecAttr::getAttributeObject (memory must be released
* by application program).
* The two methods may return different pointers.
*
* There are also methods to check attribute type, attribute size and
* array size.
* The method NdbRecAttr::arraySize returns the number of elements in the
* array (where each element is of size given by NdbRecAttr::attrSize).
* The NdbRecAttr::arraySize method is needed when reading variable-sized
* attributes.
*
* @note Variable-sized attributes are not yet supported.
*/
class NdbRecAttr
{
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
friend class NdbOperation;
friend class NdbScanOperation;
friend class NdbIndexScanOperation;
friend class NdbEventOperationImpl;
friend class NdbReceiver;
friend class Ndb;
friend class NdbQueryOperationImpl;
friend class NdbOut& operator<<(class NdbOut&, const class AttributeS&);
#endif
public:
/**
* @name Getting meta information
* @{
*/
const NdbDictionary::Column * getColumn() const;
/**
* Get type of column
* @return Data type of the column
*/
NdbDictionary::Column::Type getType() const;
/**
* Get attribute (element) size in bytes.
*
*/
Uint32 get_size_in_bytes() const { return m_size_in_bytes; }
/** @} *********************************************************************/
/**
* @name Getting stored value
* @{
*/
/**
* Check if attribute value is NULL.
*
* @return -1 = Not defined (Failure or
* NdbTransaction::execute not yet called).
* 0 = Attribute value is defined, but not equal to NULL.
* 1 = Attribute value is defined and equal to NULL.
*/
int isNULL() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return 64 bit long value.
*/
Int64 int64_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return 32 bit int value.
*/
Int32 int32_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Medium value.
*/
Int32 medium_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Short value.
*/
short short_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Char value.
*/
char char_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Int8 value.
*/
Int8 int8_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return 64 bit unsigned value.
*/
Uint64 u_64_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return 32 bit unsigned value.
*/
Uint32 u_32_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Unsigned medium value.
*/
Uint32 u_medium_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Unsigned short value.
*/
Uint16 u_short_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Unsigned char value.
*/
Uint8 u_char_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Uint8 value.
*/
Uint8 u_8_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Float value.
*/
float float_value() const;
/**
* Get value stored in NdbRecAttr object.
*
* @return Double value.
*/
double double_value() const;
/** @} *********************************************************************/
/**
* @name Getting reference to stored value
* @{
*/
/**
* Get reference to attribute value.
*
* Returns a char*-pointer to the value.
* The pointer is aligned appropriately for the data type.
* The memory is released when Ndb::closeTransaction is executed
* for the transaction which read the value.
*
* @note The memory is released by NDB API.
*
* @note The pointer to the attribute value stored in an NdbRecAttr
* object (i.e. the pointer returned by aRef) is constant.
* This means that this method can be called anytime after
* NdbOperation::getValue has been called.
*
* @return Pointer to attribute value.
*/
char* aRef() const;
/** @} *********************************************************************/
/**
* Make a copy of RecAttr object including all data.
*
* @note Copy needs to be deleted by application program.
*/
NdbRecAttr * clone() const;
/**
* Destructor
*
* @note You should only delete RecAttr-copies,
* i.e. objects that has been cloned.
*/
~NdbRecAttr();
public:
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
const NdbRecAttr* next() const;
#endif
private:
Uint32 attrId() const; /* Get attribute id */
bool setNULL(); /* Set NULL indicator */
void setUNDEFINED(); //
bool receive_data(const Uint32*, Uint32);
void release(); /* Release memory if allocated */
void init(); /* Initialise object when allocated */
NdbRecAttr(Ndb*);
void next(NdbRecAttr* aRecAttr);
NdbRecAttr* next();
int setup(const class NdbDictionary::Column* col, char* aValue);
int setup(const class NdbColumnImpl* anAttrInfo, char* aValue);
int setup(Uint32 byteSize, char* aValue);
/* Set up attributes and buffers */
bool copyoutRequired() const; /* Need to copy data to application */
void copyout(); /* Copy from storage to application */
Uint64 theStorage[4]; /* The data storage here if <= 32 bytes */
Uint64* theStorageX; /* The data storage here if > 32 bytes */
char* theValue; /* The data storage in the application */
void* theRef; /* Pointer to one of above */
NdbRecAttr* theNext; /* Next pointer */
Uint32 theAttrId; /* The attribute id */
Int32 m_size_in_bytes;
const NdbDictionary::Column* m_column;
// not-NULL means skip length bytes and store their value here
Uint16* m_getVarValue;
friend struct Ndb_free_list_t;
NdbRecAttr(const NdbRecAttr&); // Not impl.
NdbRecAttr&operator=(const NdbRecAttr&);
};
#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
inline
NdbDictionary::Column::Type
NdbRecAttr::getType() const {
return m_column->getType();
}
inline
const NdbDictionary::Column *
NdbRecAttr::getColumn() const {
return m_column;
}
inline
Int32
NdbRecAttr::int32_value() const
{
return *(Int32*)theRef;
}
inline
short
NdbRecAttr::short_value() const
{
return *(short*)theRef;
}
inline
char
NdbRecAttr::char_value() const
{
return *(char*)theRef;
}
inline
Int8
NdbRecAttr::int8_value() const
{
return *(Int8*)theRef;
}
inline
Uint32
NdbRecAttr::u_32_value() const
{
return *(Uint32*)theRef;
}
inline
Uint16
NdbRecAttr::u_short_value() const
{
return *(Uint16*)theRef;
}
inline
Uint8
NdbRecAttr::u_char_value() const
{
return *(Uint8*)theRef;
}
inline
Uint8
NdbRecAttr::u_8_value() const
{
return *(Uint8*)theRef;
}
inline
void
NdbRecAttr::release()
{
if (theStorageX != 0) {
delete [] theStorageX;
theStorageX = 0;
}
}
inline
void
NdbRecAttr::init()
{
theStorageX = 0;
theValue = 0;
theRef = 0;
theNext = 0;
theAttrId = 0xFFFF;
m_getVarValue = 0;
}
inline
void
NdbRecAttr::next(NdbRecAttr* aRecAttr)
{
theNext = aRecAttr;
}
inline
NdbRecAttr*
NdbRecAttr::next()
{
return theNext;
}
inline
const NdbRecAttr*
NdbRecAttr::next() const
{
return theNext;
}
inline
char*
NdbRecAttr::aRef() const
{
return (char*)theRef;
}
inline
bool
NdbRecAttr::copyoutRequired() const
{
return theRef != theValue && theValue != 0;
}
inline
Uint32
NdbRecAttr::attrId() const
{
return theAttrId;
}
inline
bool
NdbRecAttr::setNULL()
{
m_size_in_bytes= 0;
return true;
}
inline
int
NdbRecAttr::isNULL() const
{
return m_size_in_bytes == 0 ? 1 : (m_size_in_bytes > 0 ? 0 : -1);
}
inline
void
NdbRecAttr::setUNDEFINED()
{
m_size_in_bytes= -1;
}
class NdbOut& operator <<(class NdbOut&, const NdbRecAttr &);
class NdbRecordPrintFormat : public NdbDictionary::NdbDataPrintFormat
{
public:
NdbRecordPrintFormat() : NdbDataPrintFormat() {};
virtual ~NdbRecordPrintFormat() {};
};
/* See also NdbDictionary::printFormattedValue() */
NdbOut&
ndbrecattr_print_formatted(NdbOut& out, const NdbRecAttr &r,
const NdbRecordPrintFormat &f);
#endif // ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
#endif