TupleDescriptor.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/tuple/TupleDescriptor.cpp#23 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2005-2009 The Eigenbase Project
00005 // Copyright (C) 2003-2009 SQLstream, Inc.
00006 // Copyright (C) 2005-2009 LucidEra, Inc.
00007 // Portions Copyright (C) 1999-2009 John V. Sichi
00008 //
00009 // This program is free software; you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by the Free
00011 // Software Foundation; either version 2 of the License, or (at your option)
00012 // any later version approved by The Eigenbase Project.
00013 //
00014 // This program is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this program; if not, write to the Free Software
00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 */
00023 
00024 #include "fennel/common/CommonPreamble.h"
00025 #include "fennel/tuple/TupleDescriptor.h"
00026 #include "fennel/tuple/TupleData.h"
00027 #include "fennel/tuple/StandardTypeDescriptor.h"
00028 #include "fennel/tuple/StoredTypeDescriptor.h"
00029 #include "fennel/tuple/StoredTypeDescriptorFactory.h"
00030 #include "fennel/common/DataVisitor.h"
00031 #include "fennel/common/ByteInputStream.h"
00032 #include "fennel/common/ByteOutputStream.h"
00033 
00034 // REVIEW:  this is here for netinet/in.h platform independence, but shouldn't
00035 // need to include the whole thing
00036 #include "fennel/tuple/AttributeAccessorImpl.h"
00037 
00038 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/tuple/TupleDescriptor.cpp#23 $");
00039 
00040 TupleAttributeDescriptor::TupleAttributeDescriptor()
00041 {
00042     pTypeDescriptor = NULL;
00043     isNullable = false;
00044     cbStorage = 0;
00045 }
00046 
00047 TupleAttributeDescriptor::TupleAttributeDescriptor(
00048     StoredTypeDescriptor const &typeDescriptor,
00049     bool isNullableInit,
00050     TupleStorageByteLength cbStorageInit)
00051 {
00052     pTypeDescriptor = &typeDescriptor;
00053     isNullable = isNullableInit;
00054     if (cbStorageInit) {
00055         uint cbFixed = typeDescriptor.getFixedByteCount();
00056         assert(!cbFixed || (cbFixed == cbStorageInit));
00057         cbStorage = cbStorageInit;
00058     } else {
00059         cbStorage = typeDescriptor.getFixedByteCount();
00060     }
00061 }
00062 
00063 bool TupleAttributeDescriptor::operator == (
00064     TupleAttributeDescriptor const &other) const
00065 {
00066     return
00067         (pTypeDescriptor->getOrdinal() == other.pTypeDescriptor->getOrdinal())
00068         && (isNullable == other.isNullable)
00069         && (cbStorage == other.cbStorage);
00070 }
00071 
00072 void TupleDescriptor::projectFrom(
00073     TupleDescriptor const &tupleDescriptor,
00074     TupleProjection const &tupleProjection)
00075 {
00076     clear();
00077     for (uint i = 0; i < tupleProjection.size(); ++i) {
00078         push_back(tupleDescriptor[tupleProjection[i]]);
00079     }
00080 }
00081 
00082 int TupleDescriptor::compareTuples(
00083     TupleData const &tuple1,
00084     TupleData const &tuple2) const
00085 {
00086     int keyComp;
00087     // REVIEW:  should pass n as a param instead of recalculating it each time
00088     size_t keyCount = std::min(tuple1.size(),tuple2.size());
00089     keyCount = std::min(keyCount,size());
00090     keyComp = compareTuplesKey(tuple1, tuple2, keyCount);
00091     return keyComp;
00092 }
00093 
00094 int TupleDescriptor::compareTuples(
00095     TupleData const &tuple1, TupleProjection const &proj1,
00096     TupleData const &tuple2, TupleProjection const &proj2,
00097     bool *containsNullKey) const
00098 {
00099     size_t keyCount = std::min(proj1.size(), proj2.size());
00100 
00101     if (containsNullKey) {
00102         *containsNullKey = false;
00103     }
00104     for (uint i = 0; i < keyCount; ++i) {
00105         TupleDatum const &datum1 = tuple1[proj1[i]];
00106         TupleDatum const &datum2 = tuple2[proj2[i]];
00107         // TODO:  parameterize NULL-value collation
00108         if (!datum1.pData) {
00109             if (containsNullKey) {
00110                 *containsNullKey = true;
00111             }
00112             if (!datum2.pData) {
00113                 continue;
00114             }
00115             return -(i + 1);
00116         } else if (!datum2.pData) {
00117             if (containsNullKey) {
00118                 *containsNullKey = true;
00119             }
00120             return (i + 1);
00121         }
00122         int c = (*this)[i].pTypeDescriptor->compareValues(
00123             datum1.pData,
00124             datum1.cbData,
00125             datum2.pData,
00126             datum2.cbData);
00127         if (c > 0) {
00128             return (i + 1);
00129         } else if (c < 0) {
00130             return -(i + 1);
00131         }
00132     }
00133     return 0;
00134 
00135 }
00136 
00137 int TupleDescriptor::compareTuplesKey(
00138     TupleData const &tuple1,
00139     TupleData const &tuple2,
00140     uint keyCount) const
00141 {
00142     assert(keyCount <= std::min(tuple1.size(), tuple2.size()));
00143 
00144     for (uint i = 0; i < keyCount; ++i) {
00145         TupleDatum const &datum1 = tuple1[i];
00146         TupleDatum const &datum2 = tuple2[i];
00147         // TODO:  parameterize NULL-value collation
00148         if (!datum1.pData) {
00149             if (!datum2.pData) {
00150                 continue;
00151             }
00152             return -(i + 1);
00153         } else if (!datum2.pData) {
00154             return (i + 1);
00155         }
00156         int c = (*this)[i].pTypeDescriptor->compareValues(
00157             datum1.pData,
00158             datum1.cbData,
00159             datum2.pData,
00160             datum2.cbData);
00161         if (c > 0) {
00162             return (i + 1);
00163         } else if (c < 0) {
00164             return -(i + 1);
00165         }
00166     }
00167     return 0;
00168 }
00169 
00170 void TupleDescriptor::visit(
00171     TupleData const &tuple,
00172     DataVisitor &dataVisitor,
00173     bool visitLengths) const
00174 {
00175     for (uint i = 0; i < tuple.size(); ++i) {
00176         if (!tuple[i].pData) {
00177             if (visitLengths) {
00178                 dataVisitor.visitUnsignedInt(0);
00179             }
00180             dataVisitor.visitBytes(NULL,0);
00181         } else {
00182             if (visitLengths) {
00183                 dataVisitor.visitUnsignedInt(tuple[i].cbData);
00184             }
00185             (*this)[i].pTypeDescriptor->visitValue(
00186                 dataVisitor,
00187                 tuple[i].pData,
00188                 tuple[i].cbData);
00189         }
00190     }
00191 }
00192 
00193 // NOTE: read comments on struct StoredNode before modifying the persistence
00194 // code below.  Also note that we use specific type sizes and network byte order
00195 // since TupleDescriptors may be transmitted as binary over the network/JNI.
00196 // May want to use XML for that instead and make this code perform better
00197 // (since it's used by transaction logging).
00198 
00199 void TupleDescriptor::writePersistent(ByteOutputStream &stream) const
00200 {
00201     uint32_t iData = htonl(size());
00202     stream.writeValue(iData);
00203     for (uint i = 0; i < size(); ++i) {
00204         TupleAttributeDescriptor const &attrDesc = (*this)[i];
00205         iData = htonl(attrDesc.pTypeDescriptor->getOrdinal());
00206         stream.writeValue(iData);
00207         iData = htonl(attrDesc.isNullable);
00208         stream.writeValue(iData);
00209         // Assume TupleAttributeDescriptor is long in htonl()
00210         iData = htonl(attrDesc.cbStorage);
00211         stream.writeValue(iData);
00212     }
00213 }
00214 
00215 void TupleDescriptor::readPersistent(
00216     ByteInputStream &stream,
00217     StoredTypeDescriptorFactory const &typeFactory)
00218 {
00219     clear();
00220     uint32_t n;
00221     stream.readValue(n);
00222     n = ntohl(n);
00223     for (uint i = 0; i < n; ++i) {
00224         uint32_t iData;
00225         stream.readValue(iData);
00226         StoredTypeDescriptor const &typeDescriptor =
00227             typeFactory.newDataType(ntohl(iData));
00228         stream.readValue(iData);
00229         bool isNullable = ntohl(iData);
00230         stream.readValue(iData);
00231         TupleStorageByteLength cbStorage = ntohl(iData);
00232         push_back(
00233             TupleAttributeDescriptor(
00234                 typeDescriptor,isNullable,cbStorage));
00235     }
00236 }
00237 
00238 void TupleProjection::writePersistent(
00239     ByteOutputStream &stream) const
00240 {
00241     uint32_t iData = htonl(size());
00242     stream.writeValue(iData);
00243     for (uint i = 0; i < size(); ++i) {
00244         iData = htonl((*this)[i]);
00245         stream.writeValue(iData);
00246     }
00247 }
00248 
00249 void TupleProjection::readPersistent(
00250     ByteInputStream &stream)
00251 {
00252     clear();
00253     uint32_t n;
00254     stream.readValue(n);
00255     n = ntohl(n);
00256     for (uint i = 0; i < n; ++i) {
00257         uint32_t iData;
00258         stream.readValue(iData);
00259         push_back(ntohl(iData));
00260     }
00261 }
00262 
00263 void TupleProjection::projectFrom(
00264     TupleProjection const &sourceProjection,
00265     TupleProjection const &tupleProjection)
00266 {
00267     clear();
00268     for (uint i = 0; i < tupleProjection.size(); ++i) {
00269         push_back(sourceProjection[tupleProjection[i]]);
00270     }
00271 }
00272 
00273 bool TupleDescriptor::containsNullable() const
00274 {
00275     for (uint i = 0; i < size(); ++i) {
00276         if ((*this)[i].isNullable) {
00277             return true;
00278         }
00279     }
00280     return false;
00281 }
00282 
00283 bool TupleDescriptor::storageEqual(
00284     TupleDescriptor const &other) const
00285 {
00286     uint sz = size();
00287     if (other.size() != sz) {
00288         return false;
00289     }
00290 
00291     TupleAttributeDescriptor const * us;
00292     TupleAttributeDescriptor const * them;
00293 
00294     for (uint i = 0; i < sz; ++i) {
00295         us = &(*this)[i];
00296         them = &other[i];
00297         if ((us->pTypeDescriptor->getOrdinal() !=
00298              them->pTypeDescriptor->getOrdinal()) ||
00299             us->cbStorage != them->cbStorage) {
00300             return false;
00301         }
00302     }
00303     return true;
00304 }
00305 
00306 TupleStorageByteLength TupleDescriptor::getMaxByteCount() const
00307 {
00308     TupleStorageByteLength length = 0;
00309 
00310     for (uint i = 0; i < size(); i ++) {
00311         length += (*this)[i].cbStorage;
00312     }
00313     return length;
00314 }
00315 
00316 std::ostream &operator<<(std::ostream &str,TupleDescriptor const &tupleDesc)
00317 {
00318     str << "{" << std::endl;
00319     for (uint i = 0; i < tupleDesc.size(); ++i) {
00320         str << "\t" << i << ":  ";
00321         str << tupleDesc[i];
00322         str << std::endl;
00323     }
00324     str << "}" << std::endl;
00325     return str;
00326 }
00327 
00328 std::ostream &operator<<(
00329     std::ostream &str,
00330     TupleAttributeDescriptor const &attrDesc)
00331 {
00332     StoredTypeDescriptor::Ordinal ordinal =
00333         attrDesc.pTypeDescriptor->getOrdinal();
00334 
00335     if (ordinal < STANDARD_TYPE_END) {
00336         str << "type = " << StandardTypeDescriptor::toString(
00337             StandardTypeDescriptorOrdinal(ordinal));
00338     } else {
00339         str << "type ordinal = " << ordinal;
00340     }
00341     str << ", isNullable = " << attrDesc.isNullable;
00342     str << ", cbStorage = " << attrDesc.cbStorage;
00343     return str;
00344 }
00345 
00346 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/tuple/TupleDescriptor.cpp#23 $");
00347 
00348 // End TupleDescriptor.cpp

Generated on Mon Jun 22 04:00:21 2009 for Fennel by  doxygen 1.5.1