aboutsummaryrefslogtreecommitdiff
path: root/contrib/native/client/src/include/drill/recordBatch.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/native/client/src/include/drill/recordBatch.hpp')
-rw-r--r--contrib/native/client/src/include/drill/recordBatch.hpp873
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