diff options
Diffstat (limited to 'contrib/native/client/src/include/drill/recordBatch.hpp')
-rw-r--r-- | contrib/native/client/src/include/drill/recordBatch.hpp | 873 |
1 files changed, 873 insertions, 0 deletions
diff --git a/contrib/native/client/src/include/drill/recordBatch.hpp b/contrib/native/client/src/include/drill/recordBatch.hpp new file mode 100644 index 000000000..c40327bfd --- /dev/null +++ b/contrib/native/client/src/include/drill/recordBatch.hpp @@ -0,0 +1,873 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RECORDBATCH_H +#define RECORDBATCH_H + + +#include <assert.h> +#include <stdint.h> +#include <stdio.h> +#include <ostream> +#include <sstream> +#include <vector> +#include <boost/lexical_cast.hpp> +#include "drill/common.hpp" +#include "drill/decimalUtils.hpp" +#include "drill/protobuf/User.pb.h" + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef DRILL_CLIENT_EXPORTS + #define DECLSPEC_DRILL_CLIENT __declspec(dllexport) + #else + #ifdef USE_STATIC_LIBDRILL + #define DECLSPEC_DRILL_CLIENT + #else + #define DECLSPEC_DRILL_CLIENT __declspec(dllimport) + #endif + #endif +#else + #if __GNUC__ >= 4 + #define DECLSPEC_DRILL_CLIENT __attribute__ ((visibility ("default"))) + #else + #define DECLSPEC_DRILL_CLIENT + #endif +#endif + + +namespace Drill { + +class FieldBatch; +class ValueVectorBase; + +//TODO: The base classes for value vectors should have abstract functions instead of implementations +//that return 'NOT IMPLEMENTED YET' + +// A Read Only Sliced byte buffer +class SlicedByteBuf{ + public: + //TODO: check the size and offset parameters. What is the largest they can be? + SlicedByteBuf(const ByteBuf_t b, size_t offset, size_t length){ + this->m_buffer=b; + this->m_start=offset; + this->m_end=offset+length-1; + this->m_length=length; + } + + // Carve a sliced buffer out of another sliced buffer + SlicedByteBuf(const SlicedByteBuf& sb, size_t offset, size_t length){ + this->m_buffer=sb.m_buffer; + this->m_start=sb.m_start+offset; + this->m_end=sb.m_start+offset+length; + this->m_length=length; + } + + //Copy ctor + SlicedByteBuf(const SlicedByteBuf& other ){ + if(this!=&other){ + this->m_buffer=other.m_buffer; + this->m_start=other.m_start; + this->m_end=other.m_end; + this->m_length=other.m_length; + } + } + + SlicedByteBuf& operator=( const SlicedByteBuf& rhs ){ + if(this!=&rhs){ + this->m_buffer=rhs.m_buffer; + this->m_start=rhs.m_start; + this->m_end=rhs.m_end; + this->m_length=rhs.m_length; + } + return *this; + } + + size_t getStart(){ + return this->m_start; + } + size_t getEnd(){ + return this->m_end; + } + size_t getLength(){ + return this->m_length; + } + + // ByteBuf_t getBuffer(){ return m_buffer;} + ByteBuf_t getSliceStart(){ return this->m_buffer+this->m_start;} + + // accessor functions + // + // TYPE getTYPE(size_t index){ + // if(index>=m_length) return 0; + // return (TYPE) m_buffer[offset+index]; + // } + + + template <typename T> T readAt(size_t index) const { + // Type T can only be an integer type + // Type T cannot be a struct of fixed size + // Because struct alignment is compiler dependent + // we can end up with a struct size that is larger + // than the buffer in the sliced buf. + assert((index + sizeof(T) <= this->m_length)); + if(index + sizeof(T) <= this->m_length) + return *((T*)(this->m_buffer+this->m_start+index)); + return 0; + + } + + uint8_t getByte(size_t index){ + return readAt<uint8_t>(index); + } + + uint32_t getUint32(size_t index){ + return readAt<uint32_t>(index); + } + + uint64_t getUint64(size_t index){ + return readAt<uint64_t>(index); + } + + ByteBuf_t getAt(size_t index){ + return this->m_buffer+m_start+index; + } + + bool getBit(size_t index){ + // refer to BitVector.java http://bit.ly/Py1jof + return ((this->m_buffer[m_start+index/8] & ( 1 << (index % 8) )) !=0); + } + private: + ByteBuf_t m_buffer; // the backing store + size_t m_start; //offset within the backing store where this slice begins + size_t m_end; //offset within the backing store where this slice ends + size_t m_length; //length +}; + +class DECLSPEC_DRILL_CLIENT ValueVectorBase{ + public: + ValueVectorBase(SlicedByteBuf *b, size_t rowCount){ + m_pBuffer=b; + m_rowCount=rowCount; + } + + virtual ~ValueVectorBase(){ + } + + // test whether the value is null in the position index + virtual bool isNull(size_t index) const { + return false; + } + + + const char* get(size_t index) const { return 0;} + virtual void getValueAt(size_t index, char* buf, size_t nChars) const =0; + + virtual const ByteBuf_t getRaw(size_t index) const { + return (ByteBuf_t)m_pBuffer->getSliceStart() ; + } + + virtual uint32_t getSize(size_t index) const=0; + //virtual uint32_t getSize(size_t index) const { + // return 0; + //} + + protected: + SlicedByteBuf* m_pBuffer; + size_t m_rowCount; +}; + +class DECLSPEC_DRILL_CLIENT ValueVectorUnimplemented:public ValueVectorBase{ + public: + ValueVectorUnimplemented(SlicedByteBuf *b, size_t rowCount):ValueVectorBase(b,rowCount){ + } + + virtual ~ValueVectorUnimplemented(){ + } + + const char* get(size_t index) const { return 0;}; + virtual void getValueAt(size_t index, char* buf, size_t nChars) const{ + *buf=0; return; + } + + virtual uint32_t getSize(size_t index) const{ return 0;}; + + protected: + SlicedByteBuf* m_pBuffer; + size_t m_rowCount; +}; + +class DECLSPEC_DRILL_CLIENT ValueVectorFixedWidth:public ValueVectorBase{ + public: + ValueVectorFixedWidth(SlicedByteBuf *b, size_t rowCount):ValueVectorBase(b, rowCount){ + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + strncpy(buf, "NOT IMPLEMENTED YET", nChars); + return; + } + + const ByteBuf_t getRaw(size_t index) const { + return this->m_pBuffer->getSliceStart()+index*this->getSize(index); + } + + uint32_t getSize(size_t index) const { + return 0; + } +}; + +template <typename VALUE_TYPE> + class ValueVectorFixed : public ValueVectorFixedWidth { + public: + ValueVectorFixed(SlicedByteBuf *b, size_t rowCount) : + ValueVectorFixedWidth(b, rowCount) {} + + VALUE_TYPE get(size_t index) const { + return m_pBuffer->readAt<VALUE_TYPE>(index * sizeof(VALUE_TYPE)); + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + std::stringstream sstr; + VALUE_TYPE value = this->get(index); + sstr << value; + strncpy(buf, sstr.str().c_str(), nChars); + } + + uint32_t getSize(size_t index) const { + return sizeof(VALUE_TYPE); + } + }; + + +class DECLSPEC_DRILL_CLIENT ValueVectorBit:public ValueVectorFixedWidth{ + public: + ValueVectorBit(SlicedByteBuf *b, size_t rowCount):ValueVectorFixedWidth(b, rowCount){ + } + bool get(size_t index) const { + #ifdef DEBUG + uint8_t b = m_pBuffer->getByte((index)/8); + uint8_t bitOffset = index%8; + uint8_t setBit = (1<<bitOffset); // sets the Nth bit. + uint8_t isSet = (b&setBit); + return isSet; + #else + return (bool)((m_pBuffer->getByte((index)/8)) & (1<< (index%8) )); + #endif + + } + void getValueAt(size_t index, char* buf, size_t nChars) const { + char str[64]; // Can't have more than 64 digits of precision + //could use itoa instead of sprintf which is slow, but it is not portable + sprintf(str, "%s", this->get(index)?"true":"false"); + strncpy(buf, str, nChars); + return; + } + uint32_t getSize(size_t index) const { + return sizeof(uint8_t); + } +}; + +template <int DECIMAL_DIGITS, int WIDTH_IN_BYTES, bool IS_SPARSE, int MAX_PRECISION = 0 > + class ValueVectorDecimal: public ValueVectorFixedWidth { + public: + ValueVectorDecimal(SlicedByteBuf* b, size_t rowCount, int32_t scale): + ValueVectorFixedWidth(b, rowCount), + m_scale(scale) + { + ; // Do nothing + } + + DecimalValue get(size_t index) const { + if (IS_SPARSE) + { + return getDecimalValueFromSparse(*m_pBuffer, index * WIDTH_IN_BYTES, DECIMAL_DIGITS, m_scale); + } + return getDecimalValueFromDense(*m_pBuffer, index * WIDTH_IN_BYTES, DECIMAL_DIGITS, m_scale, MAX_PRECISION, WIDTH_IN_BYTES); + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + const DecimalValue& val = this->get(index); + const std::string& str = boost::lexical_cast<std::string>(val.m_unscaledValue); + size_t idxDecimalMark = str.length() - m_scale; + const std::string& decStr= str.substr(0, idxDecimalMark) + "." + str.substr(idxDecimalMark, m_scale); + strncpy(buf, decStr.c_str(), nChars); + return; + } + + uint32_t getSize(size_t index) const { + return WIDTH_IN_BYTES; + } + + private: + int32_t m_scale; + }; + +template<typename VALUE_TYPE> + class ValueVectorDecimalTrivial: public ValueVectorFixedWidth { + public: + ValueVectorDecimalTrivial(SlicedByteBuf* b, size_t rowCount, int32_t scale): + ValueVectorFixedWidth(b, rowCount), + m_scale(scale) + { + ; // Do nothing + } + + DecimalValue get(size_t index) const { + return DecimalValue( + m_pBuffer->readAt<VALUE_TYPE>(index * sizeof(VALUE_TYPE)), + m_scale); + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + VALUE_TYPE value = m_pBuffer->readAt<VALUE_TYPE>(index * sizeof(VALUE_TYPE)); + const std::string& str = boost::lexical_cast<std::string>(value); + size_t idxDecimalMark = str.length() - m_scale; + const std::string& decStr= str.substr(0, idxDecimalMark) + "." + str.substr(idxDecimalMark, m_scale); + strncpy(buf, decStr.c_str(), nChars); + return; + } + + uint32_t getSize(size_t index) const { + return sizeof(VALUE_TYPE); + } + + private: + int32_t m_scale; + }; + + +template <typename VALUE_TYPE> + class NullableValueVectorFixed : public ValueVectorBase +{ + public: + NullableValueVectorFixed(SlicedByteBuf *b, size_t rowCount):ValueVectorBase(b, rowCount){ + size_t offsetEnd = rowCount/8 + 1; + this->m_pBitmap= new SlicedByteBuf(*b, 0, offsetEnd); + this->m_pData= new SlicedByteBuf(*b, offsetEnd, b->getLength()); + // TODO: testing boundary case(null columns) + } + + ~NullableValueVectorFixed(){ + delete this->m_pBitmap; + delete this->m_pData; + } + + // test whether the value is null in the position index + bool isNull(size_t index) const { + return (m_pBitmap->getBit(index)==0); + } + + VALUE_TYPE get(size_t index) const { + // it should not be called if the value is null + assert( "value is null" && !isNull(index)); + return m_pData->readAt<VALUE_TYPE>(index * sizeof(VALUE_TYPE)); + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + assert( "value is null" && !isNull(index)); + std::stringstream sstr; + VALUE_TYPE value = this->get(index); + sstr << value; + strncpy(buf, sstr.str().c_str(), nChars); + } + + uint32_t getSize(size_t index) const { + assert("value is null" && !isNull(index)); + return sizeof(VALUE_TYPE); + } + private: + SlicedByteBuf* m_pBitmap; + SlicedByteBuf* m_pData; +}; + +// The 'holder' classes are (by contract) simple structs with primitive members and no dynamic allocations. +// The template classes create an instance of the class and return it to the caller in the 'get' routines. +// The compiler will create a copy and return it to the caller. If the object is more complex than a struct of +// primitives, the class _must_ provide a copy constructor. +// We don't really need a destructor here, but we declare a virtual dtor in the base class in case we ever get +// more complex and start doing dynamic allocations in these classes. + +struct DateTimeBase{ + DateTimeBase(){m_datetime=0;} + virtual ~DateTimeBase(){} + uint64_t m_datetime; + virtual void load() =0; + virtual std::string toString()=0; +}; + +struct DateHolder: public virtual DateTimeBase{ + DateHolder(){}; + DateHolder(uint64_t d){m_datetime=d; load();} + uint32_t m_year; + uint32_t m_month; + uint32_t m_day; + void load(); + std::string toString(); +}; + +struct TimeHolder: public virtual DateTimeBase{ + TimeHolder(){}; + TimeHolder(uint32_t d){m_datetime=d; load();} + uint32_t m_hr; + uint32_t m_min; + uint32_t m_sec; + uint32_t m_msec; + void load(); + std::string toString(); +}; + +struct DateTimeHolder: public DateHolder, public TimeHolder{ + DateTimeHolder(){}; + DateTimeHolder(uint64_t d){m_datetime=d; load();} + void load(); + std::string toString(); +}; + +struct DateTimeTZHolder: public DateTimeHolder{ + DateTimeTZHolder(ByteBuf_t b){ + m_datetime=*(uint64_t*)b; + m_tzIndex=*(uint32_t*)(b+sizeof(uint64_t)); + load(); + } + void load(); + std::string toString(); + int32_t m_tzIndex; + static uint32_t size(){ return sizeof(uint64_t)+sizeof(uint32_t); } + +}; + +struct IntervalYearHolder{ + IntervalYearHolder(ByteBuf_t b){ + m_month=*(uint32_t*)b; + load(); + } + void load(){}; + std::string toString(); + uint32_t m_month; + static uint32_t size(){ return sizeof(uint32_t); } +}; + +struct IntervalDayHolder{ + IntervalDayHolder(ByteBuf_t b){ + m_day=*(uint32_t*)(b); + m_ms=*(uint32_t*)(b+sizeof(uint32_t)); + load(); + } + void load(){}; + std::string toString(); + uint32_t m_day; + uint32_t m_ms; + static uint32_t size(){ return 2*sizeof(uint32_t)+4; } +}; + +struct IntervalHolder{ + IntervalHolder(ByteBuf_t b){ + m_month=*(uint32_t*)b; + m_day=*(uint32_t*)(b+sizeof(uint32_t)); + m_ms=*(uint32_t*)(b+2*sizeof(uint32_t)); + load(); + } + void load(){}; + std::string toString(); + uint32_t m_month; + uint32_t m_day; + uint32_t m_ms; + static uint32_t size(){ return 3*sizeof(uint32_t)+4; } +}; + +/* + * VALUEHOLDER_CLASS_TYPE is a struct with a constructor that takes a parameter of type VALUE_VECTOR_TYPE + * (a primitive type) + * VALUEHOLDER_CLASS_TYPE implements a toString function + * Note that VALUEHOLDER_CLASS_TYPE is created on the stack and the copy returned in the get function. + * So the class needs to have the appropriate copy constructor or the default bitwise copy should work + * correctly. + */ +template <class VALUEHOLDER_CLASS_TYPE, typename VALUE_TYPE> + class ValueVectorTyped:public ValueVectorFixedWidth{ + public: + ValueVectorTyped(SlicedByteBuf *b, size_t rowCount) : + ValueVectorFixedWidth(b, rowCount) {} + + + VALUEHOLDER_CLASS_TYPE get(size_t index) const { + VALUE_TYPE v= m_pBuffer->readAt<VALUE_TYPE>(index * sizeof(VALUE_TYPE)); + VALUEHOLDER_CLASS_TYPE r(v); + return r; + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + std::stringstream sstr; + VALUEHOLDER_CLASS_TYPE value = this->get(index); + sstr << value.toString(); + strncpy(buf, sstr.str().c_str(), nChars); + } + + uint32_t getSize(size_t index) const { + return sizeof(VALUE_TYPE); + } + }; + +template <class VALUEHOLDER_CLASS_TYPE> + class ValueVectorTypedComposite:public ValueVectorFixedWidth{ + public: + ValueVectorTypedComposite(SlicedByteBuf *b, size_t rowCount) : + ValueVectorFixedWidth(b, rowCount) {} + + + VALUEHOLDER_CLASS_TYPE get(size_t index) const { + ByteBuf_t b= m_pBuffer->getAt(index * getSize(index)); + VALUEHOLDER_CLASS_TYPE r(b); + return r; + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + std::stringstream sstr; + VALUEHOLDER_CLASS_TYPE value = this->get(index); + sstr << value.toString(); + strncpy(buf, sstr.str().c_str(), nChars); + } + + uint32_t getSize(size_t index) const { + return VALUEHOLDER_CLASS_TYPE::size(); + } + }; + +template <class VALUEHOLDER_CLASS_TYPE, class VALUE_VECTOR_TYPE> + class NullableValueVectorTyped : public ValueVectorBase { + public: + + NullableValueVectorTyped(SlicedByteBuf *b, size_t rowCount):ValueVectorBase(b, rowCount){ + size_t offsetEnd = rowCount/8 + 1; + this->m_pBitmap= new SlicedByteBuf(*b, 0, offsetEnd); + this->m_pData= new SlicedByteBuf(*b, offsetEnd, b->getLength()-offsetEnd); + this->m_pVector= new VALUE_VECTOR_TYPE(m_pData, rowCount); + } + + ~NullableValueVectorTyped(){ + delete this->m_pBitmap; + delete this->m_pData; + delete this->m_pVector; + } + + bool isNull(size_t index) const{ + return (m_pBitmap->getBit(index)==0); + } + + VALUEHOLDER_CLASS_TYPE get(size_t index) const { + assert(!isNull(index)); + return m_pVector->get(index); + } + + void getValueAt(size_t index, char* buf, size_t nChars) const{ + std::stringstream sstr; + if(this->isNull(index)){ + sstr<<"NULL"; + strncpy(buf, sstr.str().c_str(), nChars); + }else{ + return m_pVector->getValueAt(index, buf, nChars); + } + } + + uint32_t getSize(size_t index) const { + assert(!isNull(index)); + return this->m_pVector->getSize(index); + } + + private: + SlicedByteBuf* m_pBitmap; + SlicedByteBuf* m_pData; + VALUE_VECTOR_TYPE* m_pVector; + }; + +class DECLSPEC_DRILL_CLIENT VarWidthHolder{ + public: + ByteBuf_t data; + size_t size; +}; + +class DECLSPEC_DRILL_CLIENT ValueVectorVarWidth:public ValueVectorBase{ + public: + ValueVectorVarWidth(SlicedByteBuf *b, size_t rowCount):ValueVectorBase(b, rowCount){ + size_t offsetEnd = (rowCount+1)*sizeof(uint32_t); + this->m_pOffsetArray= new SlicedByteBuf(*b, 0, offsetEnd); + this->m_pData= new SlicedByteBuf(*b, offsetEnd, b->getLength()); + } + ~ValueVectorVarWidth(){ + delete this->m_pOffsetArray; + delete this->m_pData; + } + + VarWidthHolder get(size_t index) const { + size_t startIdx = this->m_pOffsetArray->getUint32(index*sizeof(uint32_t)); + size_t endIdx = this->m_pOffsetArray->getUint32((index+1)*sizeof(uint32_t)); + size_t length = endIdx - startIdx; + assert(length >= 0); + // Return an object created on the stack. The compiler will return a + // copy and destroy the stack object. The optimizer will hopefully + // elide this so we can return an object with no extra memory allocation + // and no copies.(SEE: http://en.wikipedia.org/wiki/Return_value_optimization) + VarWidthHolder dst; + dst.data=this->m_pData->getSliceStart()+startIdx; + dst.size=length; + return dst; + } + + void getValueAt(size_t index, char* buf, size_t nChars) const { + size_t startIdx = this->m_pOffsetArray->getUint32(index*sizeof(uint32_t)); + size_t endIdx = this->m_pOffsetArray->getUint32((index+1)*sizeof(uint32_t)); + size_t length = endIdx - startIdx; + size_t copyChars=0; + assert(length >= 0); + copyChars=nChars<=length?nChars:length; + memcpy(buf, this->m_pData->getSliceStart()+startIdx, copyChars); + return; + } + + const ByteBuf_t getRaw(size_t index) const { + size_t startIdx = this->m_pOffsetArray->getUint32(index*sizeof(uint32_t)); + size_t endIdx = this->m_pOffsetArray->getUint32((index+1)*sizeof(uint32_t)); + size_t length = endIdx - startIdx; + assert(length >= 0); + return this->m_pData->getSliceStart()+startIdx; + } + + uint32_t getSize(size_t index) const { + size_t startIdx = this->m_pOffsetArray->getUint32(index*sizeof(uint32_t)); + size_t endIdx = this->m_pOffsetArray->getUint32((index+1)*sizeof(uint32_t)); + size_t length = endIdx - startIdx; + assert(length >= 0); + return length; + } + private: + SlicedByteBuf* m_pOffsetArray; + SlicedByteBuf* m_pData; +}; + +class DECLSPEC_DRILL_CLIENT ValueVectorVarChar:public ValueVectorVarWidth{ + public: + ValueVectorVarChar(SlicedByteBuf *b, size_t rowCount):ValueVectorVarWidth(b, rowCount){ + } + VarWidthHolder get(size_t index) const { + return ValueVectorVarWidth::get(index); + } +}; + +class DECLSPEC_DRILL_CLIENT ValueVectorVarBinary:public ValueVectorVarWidth{ + public: + ValueVectorVarBinary(SlicedByteBuf *b, size_t rowCount):ValueVectorVarWidth(b, rowCount){ + } +}; +// +//TODO: For windows, we have to export instantiations of the template class. +//see: http://msdn.microsoft.com/en-us/library/twa2aw10.aspx +//for example: +//template class __declspec(dllexport) B<int>; +//class __declspec(dllexport) D : public B<int> { } +// +// -------------------------------------------------------------------------------------- +// TODO: alias for all value vector types +// -------------------------------------------------------------------------------------- +typedef NullableValueVectorTyped<int, ValueVectorBit > NullableValueVectorBit; +// Aliases for Decimal Types: +// The definitions for decimal digits, width, max precision are defined in +// /exec/java-exec/src/main/codegen/data/ValueVectorTypes.tdd +// +// Decimal9 and Decimal18 could be optimized, maybe write seperate classes? +typedef ValueVectorDecimalTrivial<int32_t> ValueVectorDecimal9; +typedef ValueVectorDecimalTrivial<int64_t> ValueVectorDecimal18; +typedef ValueVectorDecimal<3, 12, false, 28> ValueVectorDecimal28Dense; +typedef ValueVectorDecimal<4, 16, false, 38> ValueVectorDecimal38Dense; +typedef ValueVectorDecimal<5, 20, true, 28> ValueVectorDecimal28Sparse; +typedef ValueVectorDecimal<6, 24, true, 38> ValueVectorDecimal38Sparse; + +typedef NullableValueVectorTyped<int32_t, ValueVectorDecimal9> NullableValueVectorDecimal9; +typedef NullableValueVectorTyped<int64_t, ValueVectorDecimal18> NullableValueVectorDecimal18; +typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal28Dense> NullableValueVectorDecimal28Dense; +typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal38Dense> NullableValueVectorDecimal38Dense; +typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal28Sparse> NullableValueVectorDecimal28Sparse; +typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal38Sparse> NullableValueVectorDecimal38Sparse; + +typedef ValueVectorTyped<DateHolder, uint64_t> ValueVectorDate; +typedef ValueVectorTyped<DateTimeHolder, uint64_t> ValueVectorTimestamp; +typedef ValueVectorTyped<TimeHolder, uint32_t> ValueVectorTime; +typedef ValueVectorTypedComposite<DateTimeTZHolder> ValueVectorTimestampTZ; +typedef ValueVectorTypedComposite<IntervalHolder> ValueVectorInterval; +typedef ValueVectorTypedComposite<IntervalDayHolder> ValueVectorIntervalDay; +typedef ValueVectorTypedComposite<IntervalYearHolder> ValueVectorIntervalYear; + +typedef NullableValueVectorTyped<DateHolder, ValueVectorDate> NullableValueVectorDate; +typedef NullableValueVectorTyped<DateTimeHolder, ValueVectorTimestamp> NullableValueVectorTimestamp; +typedef NullableValueVectorTyped<TimeHolder, ValueVectorTime> NullableValueVectorTime; +typedef NullableValueVectorTyped<DateTimeTZHolder, ValueVectorTimestampTZ> NullableValueVectorTimestampTZ; +typedef NullableValueVectorTyped<IntervalHolder, ValueVectorInterval> NullableValueVectorInterval; +typedef NullableValueVectorTyped<IntervalDayHolder, ValueVectorIntervalDay> NullableValueVectorIntervalDay; +typedef NullableValueVectorTyped<IntervalYearHolder, ValueVectorIntervalYear> NullableValueVectorIntervalYear; + +class DECLSPEC_DRILL_CLIENT FieldMetadata{ + public: + FieldMetadata(){}; + void set(const exec::shared::SerializedField& f){ + m_name=f.name_part().name(); + m_minorType=f.major_type().minor_type(); + m_dataMode=f.major_type().mode(); + m_valueCount=f.value_count(); + m_scale=f.major_type().scale(); + m_precision=f.major_type().precision(); + m_bufferLength=f.buffer_length(); + } + const std::string& getName(){ return m_name;} + common::MinorType getMinorType() const{ return m_minorType;} + common::DataMode getDataMode() const{return m_dataMode;} + uint32_t getValueCount() const{return m_valueCount;} + uint32_t getScale() const{return m_scale;} + uint32_t getBufferLength() const{return m_bufferLength;} + void copy(Drill::FieldMetadata& f){ + m_name=f.m_name; + m_minorType=f.m_minorType; + m_dataMode=f.m_dataMode; + m_valueCount=f.m_valueCount; + m_scale=f.m_scale; + m_precision=f.m_precision; + m_bufferLength=f.m_bufferLength; + } + + private: + //exec::shared::FieldMetadata* m_pFieldMetadata; + std::string m_name; + common::MinorType m_minorType; + common::DataMode m_dataMode; + uint32_t m_valueCount; + uint32_t m_scale; + uint32_t m_precision; + uint32_t m_bufferLength; +}; + +class FieldBatch{ + public: + FieldBatch(const Drill::FieldMetadata& fmd, const ByteBuf_t data, size_t start, size_t length): + m_fieldMetadata(fmd){ + m_pValueVector=NULL; + m_pFieldData=new SlicedByteBuf(data, start, length); + } + + ~FieldBatch(){ + if(m_pFieldData!=NULL){ + delete m_pFieldData; m_pFieldData=NULL; + } + if(m_pValueVector!=NULL){ + delete m_pValueVector; m_pValueVector=NULL; + } + } + + // Loads the data into a Value Vector ofappropriate type + ret_t load(); + + const ValueVectorBase * getVector(){ + return m_pValueVector; + } + + private: + const Drill::FieldMetadata& m_fieldMetadata; + ValueVectorBase * m_pValueVector; + SlicedByteBuf * m_pFieldData; + +}; + +class ValueVectorFactory{ + public: + static ValueVectorBase* allocateValueVector(const Drill::FieldMetadata & fmd, SlicedByteBuf *b); +}; + +class DECLSPEC_DRILL_CLIENT RecordBatch{ + public: + RecordBatch(exec::user::QueryResult* pResult, ByteBuf_t b){ + m_pQueryResult=pResult; + m_pRecordBatchDef=&pResult->def(); + m_numRecords=pResult->row_count(); + m_buffer=b; + m_numFields=pResult->def().field_size(); + m_bHasSchemaChanged=false; + } + + ~RecordBatch(){ + m_buffer=NULL; + //free memory allocated for FieldBatch objects saved in m_fields; + for(std::vector<FieldBatch*>::iterator it = m_fields.begin(); it != m_fields.end(); ++it){ + delete *it; + } + m_fields.clear(); + for(std::vector<Drill::FieldMetadata*>::iterator it = m_fieldDefs.begin(); it != m_fieldDefs.end(); ++it){ + delete *it; + } + m_fieldDefs.clear(); + delete m_pQueryResult; + } + + // get the ith field metadata + const Drill::FieldMetadata& getFieldMetadata(size_t index){ + //return this->m_pRecordBatchDef->field(index); + return *(m_fieldDefs[index]); + } + + size_t getNumRecords(){ return m_numRecords;} + std::vector<FieldBatch*>& getFields(){ return m_fields;} + size_t getNumFields() { return m_pRecordBatchDef->field_size(); } + bool isLastChunk() { return m_pQueryResult->is_last_chunk(); } + + std::vector<Drill::FieldMetadata*>& getColumnDefs(){ return m_fieldDefs;} + + // + // build the record batch: i.e. fill up the value vectors from the buffer. + // On fetching the data from the server, the caller creates a RecordBatch + // object then calls build() to build the value vectors.The caller saves the + // Record Batch and is responsible for freeing both the RecordBatch and the + // raw buffer memory + // + ret_t build(); + + void print(std::ostream& s, size_t num); + + const ValueVectorBase * getVector(size_t index){ + return m_fields[index]->getVector(); + } + + void schemaChanged(bool b){ + this->m_bHasSchemaChanged=b; + } + + bool hasSchemaChanged(){ return m_bHasSchemaChanged;} + + #ifdef DEBUG + const exec::user::QueryResult* getQueryResult(){ return this->m_pQueryResult;} + #endif + private: + const exec::user::QueryResult* m_pQueryResult; + const exec::shared::RecordBatchDef* m_pRecordBatchDef; + ByteBuf_t m_buffer; + //build the current schema out of the field metadata + std::vector<Drill::FieldMetadata*> m_fieldDefs; + std::vector<FieldBatch*> m_fields; + size_t m_numFields; + size_t m_numRecords; + bool m_bHasSchemaChanged; + +}; // RecordBatch + +} // namespace + +#endif |