Files
secondo/include/Attribute.h
2026-01-23 17:03:45 +08:00

790 lines
19 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004-2007, University in Hagen, Faculty of Mathematics and
Computer Science, Database Systems for New Applications.
SECONDO 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; either version 2 of the License, or
(at your option) any later version.
SECONDO 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 SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
1 Header File: Attribute
May 1998 Stefan Dieker
April 2002 Ulrich Telle Adjustments for the new Secondo version
Oct 2004 M. Spiekermann. Adding some more detailed documentation and some
thoughts about redesign and performance.
January 2006, M. Spiekermann. Some template functions which could be
used as default for some type constructor functions were moved to
ConstructorTemplates.h
May 2006, M. Spiekermann. Documentation for the ~Compare~ function
extended. Template functions ~GenericCompare~ and ~GetValue~ added.
1.1 Overview
Classes implementing attribute data types have to be subtypes of class
attribute. Whatever the shape of such derived attribute classes might be,
their instances can be aggregated and made persistent via instances of class
~Tuple~, while the user is (almost) not aware of the additional management
actions arising from persistence.
1.1 Class "Attribute"[1]
The class ~Attribute~ defines several pure virtual methods which every
derived attribute class must implement.
*/
#ifndef ATTRIBUTE_H
#define ATTRIBUTE_H
#include "SecondoSystem.h"
#include "NestedList.h"
#include "ListUtils.h"
#include "Counter.h"
//#include "AlgebraManager.h"
#include "../Tools/Flob/Flob.h"
#include "WinUnix.h"
#include "SecondoSMI.h"
#include "AlmostEqual.h"
typedef SmiRecordId TupleId;
/*
3.5 Struct ~AttrDelete~
This structure defines the way attributes are deleted. First, ~refs~
maintain a reference counter of that attribute. Many tuples can
point to the same attribute to avoid unnecessary copying. Every
tuple that points to an attribute increases this value and every
time it tries to delete the attribute, it decreses this value.
The attribute will only be delete when ~refs~ = 0.
~isDelete~ indicates which function must be called to delete the
attribute. If it is ~false~, then the attribute was created
with ~malloc~ and must be deleted with ~free~. Otherwise, if it
is ~true~, the attribute was created with ~new~ and must
be deleted with ~delete~. The default is ~DeleteAttr~.
*/
const uint8_t ONE = 1;
const uint8_t TWO = 2;
const uint8_t NOT_ONE = ~ONE;
const uint8_t NOT_TWO = ~TWO;
class AttrDelete
{
public:
AttrDelete():
refs( 1 ),delInfo(ONE)
// Note: variable isDefined belongs to the state of
// Attribute objects thus the default constructor should
// not change the value here since the default persistency
// mechanism does simply copy byte blocks of the object's
// current state!
{ SetDelete(); }
AttrDelete(bool defined): refs(1), isDefined(defined), delInfo(ONE)
{ }
AttrDelete& operator=(const AttrDelete& d){
isDefined = d.isDefined;
// do not change Construction properties
return *this;
}
void SetDelete() { delInfo = delInfo | ONE; }
void SetMalloc() { delInfo = delInfo & NOT_ONE; }
bool IsDelete() const { return (delInfo & ONE) > 0; }
void Pin() { delInfo = delInfo | TWO; }
bool IsPinned() const { return (delInfo & TWO) >0; }
uint16_t refs;
bool isDefined;
private:
uint8_t delInfo; // bit 1 : isDelete
// bit 2 : isPinned
};
/*
4 Class ~Attribute~
*/
// forward declaration
class Tuple;
class Attribute
{
// allow a Tuple to manipulate the reference counter
// directly
friend class Tuple;
public:
inline Attribute()
{}
/*
The simple constructor.
*/
Attribute(bool defined) : del(defined) {}
Attribute(const Attribute& a) : del(a.del.isDefined) {}
inline virtual ~Attribute()
{}
/*
The virtual destructor.
*/
virtual bool IsDefined() const { return del.isDefined; }
/*
Returns whether the attribute is defined.
*/
bool IsPinned() const { return del.IsPinned(); }
/*
Checks whether this attrobute is pinned. This means if
~DeleteIfAllowed~ is called, native flobs are not destroyed.
*/
void Pin() { del.Pin(); }
/*
Marks this attribute to be pinned, i.e. persistent stored in an
tenporal buffer.
*/
virtual void SetDefined(bool defined) { del.isDefined = defined; }
/*
Sets the ~defined~ flag of the attribute.
*/
virtual size_t Sizeof() const = 0;
/*
Returns the ~sizeof~ of the attribute class.
*/
Attribute& operator=(const Attribute& a){
del = a.del;
return *this;
}
virtual size_t GetMemSize() {
return Sizeof() + getUncontrolledFlobSize();
}
/*
Returns the size of the object in main memory
*/
virtual void bringToMemory(){
for(int i=0;i<NumOfFLOBs();i++){
this->GetFLOB(i)->bringToMemory();
}
}
/*
transfers the flob data from disk to main memory.
*/
/*
Returns the size of uncotrolled flob memory.
*/
size_t getUncontrolledFlobSize() {
size_t res = 0;
for(int i=0;i<NumOfFLOBs();i++){
res += GetFLOB(i)->getUncontrolledSize();
}
return res;
}
/*
Checks whether the argument is in Kind DATA.
*/
static bool checkType(const ListExpr type){
return listutils::isDATA(type);
}
virtual int Compare( const Attribute *rhs ) const = 0;
/*
This function should define an order on the attribute values.
The implementation must also consider that values may be undefined.
Hence there are four cases of defined/undefined combinations which are
below referred as 11, 00, 01, 10.
Case 11 (both values are defined) is the ~normal~ comparison
of attribute values
----
-1: *this < *rhs
0: *this = *rhs
1: *this > *rhs
----
The semantics for the other cases are defined below:
----
01 -> -1: *this < *rhs
00 -> 0: *this = *rhs
10 -> 1: *this > *rhs
----
Thus the result of a comparison of attribute values is never undefined!
*/
virtual int CompareAlmost( const Attribute *rhs ) const
{
static long& ctr = Counter::getRef("ATTR::CompareAlmost");
ctr++;
return Compare(rhs);
}
/*
This function is for unprecise datatypes like ~real~ or ~point~, where one
needs to distinguish the ordinary ~Compare~, which will be used for sorting
and precise comparison/lookup in DBArrays, and the fuzzy version, which employs
~AlmostEqual~ instead of ~Equal~. It will be used to remove duplicates, gouping
etc.
For unprecise datatypes, you should always overwrite ~CompareAlmost~.
*/
/*
Below a generic compare function is implemented by means of templates.
In order to use this implement the functions
----
inline operator==(const T& rhs) const
inline operator<(const T& rhs) const
----
in your class and instantiate it inside your ~Compare~ function implementation.
For examples refer to the ~StandardAlgebra~.
*/
template<class T>
static inline int GenericCompare( const T* left,
const T* right,
const bool lDef,
const bool rDef )
{
static long& ctr = Counter::getRef("ATTR::GenericCompare");
ctr++;
if ( lDef && rDef) // case 11: value comparison
{
if ( *left == *right )
return 0;
else
return ( *right < *left ) ? 1 : -1;
}
// compare only the defined flags
if( !lDef ) {
if ( !rDef ) // case 00
return 0;
else // case 01
return -1;
}
return 1; // case 10
}
/*
In some cases it makes sense to offer more specialized comparisons since
some algorithms like sorting or duplicate removal need only $<$ or $=$.
If it helps to increase performance one could think about to implement the
virtual ~Equal~ or ~Less~ functions in the derived classes.
*/
inline virtual bool Equal(const Attribute* rhs) const
{
static long& ctr = Counter::getRef("ATTR::Equal");
ctr++;
return Compare(rhs) == 0;
}
inline virtual bool Less(const Attribute* rhs) const
{
static long& ctr = Counter::getRef("ATTR::Less");
ctr++;
return Compare(rhs) < 0;
}
inline virtual bool LessAlmost(const Attribute* rhs) const
{
static long& ctr = Counter::getRef("ATTR::LessAlmost");
ctr++;
return CompareAlmost(rhs) < 0;
}
int CompareDefs(const Attribute* rhs) const{
if(IsDefined()==rhs->IsDefined()){
return 0;
}
return IsDefined()?1:-1;
}
virtual bool Adjacent( const Attribute *attrib ) const = 0;
/*
This function checks if two attributes are adjacent. As an example,
1 and 2 are adjacent for integer attributes and "Victor" and "Victos"
are adjacent for string attributes.
*/
inline virtual int NumOfFLOBs() const
{
return 0;
}
/*
Returns the number of FLOBs the attribute contains. The default
value of this funcion is 0, which means that if an attribute
does not contain FLOBs, it is not necessary to implement this
function.
*/
inline virtual Flob* GetFLOB( const int i __attribute__((unused)) )
{
assert( false );
return 0;
}
/*
Returns a reference to a FLOB given an index ~i~. If the attribute
does not contain any FLOBs (the default), this function should not
be called.
*/
inline virtual
void Restrict( const std::vector< std::pair<int, int> >
__attribute__((unused))& interval )
{}
/*
This function is called to restrict a current attribute to a
set of intervals. This function is used in double indexing.
*/
inline virtual void Initialize( SmiFileId __attribute__((unused)) fileId,
TupleId __attribute__((unused)) tupleId,
int __attribute__((unused)) attrno) {}
inline virtual void Finalize() {}
/*
These two functions are used to initialize and finalize values of
attributes. In some cases, the constructor and destructor are
not called, e.g. when deleting an attribute with delete type
~FreeAttr~. In these cases, these two functions are called
anyway. An example of their usage is in the JNI algebras, where
some Java initialization and destructions are done in these
functions.
*/
inline virtual std::ostream& Print( std::ostream& os ) const
{
return os << "< No Print()-function for this datatype! >";
}
inline virtual std::ostream& PrintFormatted( std::ostream& os ) const
{
return this->Print(os);
}
/*
Prints the attribute. Used for debugging purposes.
*/
inline virtual void
Serialize(char* storage, size_t sz, size_t offset) const
{
memcpy( &storage[offset], (void*)this, sz );
}
/*
Writes an attribute as byte sequence into ~storage~. The default
implementation simply writes the byte block of the current instance.
*/
inline virtual size_t SerializedSize() const
{
return 0;
}
/*
The default implementation returns 0 here. This indicates that the default
mechanism for making objects persistent is used and the data type's ~SizeOfObj~
function will be used to determine the block size to be stored on disk.
A datatype which support serialization must implement this function in order
to overwrite the default.
*/
inline virtual void Rebuild(char* state, size_t sz)
{
memcpy((char*)this, state, sz);
}
inline virtual void Rebuild(char* state, size_t sz, ObjectCast cast)
{
Rebuild(state,sz);
cast(this);
}
/*
Rebuild a stored object state given as byte sequence by ~state~. The default
implementation excpects the state contains the byte block which was produced by
the default ~Serialize~ function. The size of the object is ~sz~
*/
static Attribute* Create(char* state, size_t& offset,
const ListExpr typeInfo );
inline static Attribute*
Create(Attribute* attr, char* state, size_t sz, int algId, int typeId)
{
// call the spezialized Rebuild function, if not implemented, the default
// above will be called.
if(!attr->IsPinned()){
for (int i = 0; i < attr->NumOfFLOBs(); i++) {
attr->GetFLOB(i)->destroyIfNonPersistent();
}
}
attr->Rebuild(state, sz ,am->Cast(algId, typeId));
// Remark: the returned pointer has been created using the new operator!
return attr;
}
/*
The function above creates a new instance of the C++-class which represents
a secondo object for the given algId and typeId. By default the stored
state of an objects is defined by its byte block maintained from the C++ runtime
environment.
Subclasses of an ~Attribute~ may overwrite the ~Serialize~ and ~Rebuild~
function in order to provide a more compact object state storage representation.
*/
static void Save( SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Attribute *elem );
/*
Default save function.
*/
static Attribute *Open( SmiRecord& valueRecord,
size_t& offset, const ListExpr typeInfo );
/*
Default open function.
*/
bool DeleteIfAllowed(const bool DestroyNonPersistentFlobs = true);
/*
Decreases the Attribute's reference counter ~refs~. If ~refs~ becomes 0,
it deletes the attribute.
*/
Attribute* Copy();
inline void IncReference(){
del.refs++;
}
/*
Returns a new reference to this attribute, if possible (~refs~ < 255),
otherwise it returns a reference to a fresh clone (having ~refs~ = 1).
*/
virtual Attribute *Clone() const = 0;
/*
Clones this attribute. This function is implemented in the son classes.
~refs~ of the new clone should be set to 1! A good way to ensure this, is
to initialize ~refs~ with 1 within all constructors
(except from the standard constructor).
*/
inline void SetFreeAttr()
{
del.SetMalloc();
}
/*
Sets the delete type.
The template function below offers a generic interface for
Interaction with the query processor. This makes it easier to
retrieve parameter values inside an operators value mapping.
Examples of its usage can be found in the ~StandardAlgebra~.
In order to be able to instantiate this template you need to
implement a member function
---- S T::GetValue()
----
However, this makes only sense for types which have a simple internal
value like int, float, etc.
*/
inline int NoRefs() const{
return del.refs;
}
inline int GetNumOfRefs()const{
return del.refs;
}
/*
Returns the number of references for this attribute.
*/
template<class S, class T>
static T GetValue(Word w)
{
S* ptr = static_cast<S*>(w.addr);
return ptr->GetValue();
}
std::string AttrDelete2string();
/*
Print the delete reference info to a string (for debugging)
*/
static void InitCounters(bool show);
static void SetCounterValues(bool show);
virtual std::string getCsvStr() const{
return "";
}
/*
returns a string representation for csv export
*/
virtual bool hasTextRepresentation() const{
return false;
}
virtual std::string toText() const{
assert(false);
return "";
}
virtual bool fromText(const std::string __attribute__((unused))& value) {
SetDefined(false);
return false;
}
virtual bool hasBox() const { return false; }
virtual void writeShape(std::ostream& o, uint32_t RecNo) const{
// first, write the record header
WinUnix::writeBigEndian(o,RecNo);
uint32_t length = 2;
WinUnix::writeBigEndian(o,length);
uint32_t type = 0;
WinUnix::writeLittleEndian(o,type);
}
virtual double getMinX() const{return 0;}
virtual double getMaxX() const{return 0;}
virtual double getMinY() const{return 0;}
virtual double getMaxY() const{return 0;}
virtual double getMinZ() const { return 0.0; }
virtual double getMaxZ() const{ return 0.0; }
virtual double getMinM() const { return 0.0; }
virtual double getMaxM() const{ return 0.0; }
virtual uint32_t getshpType() const{ return 0; }
virtual bool hasDB3Representation() const {return false;}
virtual unsigned char getDB3Type() const { return 'L'; }
virtual unsigned char getDB3Length() const { return 1; }
virtual unsigned char getDB3DecimalCount(){ return 0; }
virtual std::string getDB3String() const { return "?"; }
virtual std::string getSQLType(){ return ""; }
virtual std::string getSQLRepresentation(){ return "";}
virtual void ReadFromString(std::string __attribute__((unused)) value){
SetDefined(false);
}
enum StorageType { Default, Core, Extension, Unspecified };
inline virtual StorageType GetStorageType() const { return Default; }
virtual size_t HashValue() const = 0;
/*
The hash function.
*/
virtual void CopyFrom(const Attribute* right) = 0;
/*
Copies the contents of ~right~ into ~this~. Assumes that ~this~ and
~right~ are of the same type. This can be ensured by the type checking functions
in the algebras.
The reference counter if this attribute should not be affected.
*/
virtual void DestroyFlobs();
/*
Destroys all Flobs of the Attribute, regardless of the reference counter, and
cleans them.
Call this prior to deletion of an automatic attribute variable.
Otherwise, the Flobs belonging to the Attribute are not destroyed and may
persist without being referenced any more.
*/
protected:
AttrDelete del;
/*
Stores the way this attribute is deleted.
*/
inline void InitRefs(){
del.refs=1;
}
/*
Set the reference counter to 1
*/
/*
Counters for basic operations. Useful for verifying cost formulas
and determining cost factors.
*/
static void counters(bool reset, bool show);
};
/*
Generic ~Open~-function
*/
template<class T>
bool OpenAttribute( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
T *bf = static_cast<T*>(Attribute::Open( valueRecord, offset, typeInfo ));
value = SetWord( bf );
return true;
}
/*
Generic ~Save~-function
*/
template<class T>
bool SaveAttribute( SmiRecord& valueRecord,
size_t& offset,
const ListExpr typeInfo,
Word& value )
{
T *bf = static_cast<T*>(value.addr);
Attribute::Save( valueRecord, offset, typeInfo, bf );
return true;
}
/*
The generalized output operator
*/
std::ostream& operator<<(std::ostream& os, const Attribute& attr);
/*
Pointer save DeleteIfAllowed Function
*/
template<class T>
void deleteIfAllowed(T*& victim){
if(victim){
victim->DeleteIfAllowed();
victim = 0;
}
}
#endif