| /********************************************************************** |
| // @@@ START COPYRIGHT @@@ |
| // |
| // 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. |
| // |
| // @@@ END COPYRIGHT @@@ |
| **********************************************************************/ |
| /* -*-C++-*- |
| ***************************************************************************** |
| * |
| * File: <file> |
| * Description: |
| * |
| * |
| * Created: 7/10/95 |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| #include "Platform.h" |
| |
| |
| #include "exp_stdh.h" |
| #include "exp_attrs.h" |
| #include "exp_clause_derived.h" |
| #include "exp_bignum.h" |
| #include "str.h" |
| #include "NLSConversion.h" |
| |
| Int32 Attributes::getStorageLength(){return -1;}; |
| Int32 Attributes::getDefaultValueStorageLength(){return -1;}; |
| Int32 Attributes::getLength(){return -1;}; |
| Attributes * Attributes::newCopy(){return 0;}; |
| Attributes * Attributes::newCopy(CollHeap *){return 0;}; |
| void Attributes::copyAttrs(Attributes * /*source_*/){}; |
| |
| Attributes * SimpleType::newCopy() |
| { |
| SimpleType * new_copy = new SimpleType(); |
| *new_copy = *this; |
| return new_copy; |
| } |
| |
| Attributes * SimpleType::newCopy(CollHeap * heap) |
| { |
| SimpleType * new_copy = new(heap) SimpleType(); |
| *new_copy = *this; |
| return new_copy; |
| } |
| |
| void SimpleType::copyAttrs(Attributes *source_) // copy source attrs to this. |
| { |
| *this = *(SimpleType *)source_; |
| } |
| |
| Attributes::Attributes(short complex_type) : |
| NAVersionedObject(AttribAnchorID) |
| { |
| datatype_ = -1; |
| |
| nullFlag_ = 0; |
| nullIndicatorLength_ = 2; // the default |
| |
| vcIndicatorLength_ = 2; // for now |
| |
| offset_ = ExpOffsetMax; |
| atpindex_ = 0; |
| atp_ = 0; |
| |
| nullIndOffset_ = ExpOffsetMax; |
| vcLenIndOffset_ = ExpOffsetMax; |
| voaOffset_ = ExpOffsetMax; |
| relOffset_ = 0; |
| nextAttrIdx_ = ExpOffsetMax; |
| rowsetSize_ = 0; |
| rowsetInfo_ = 0; |
| nullBitIdx_ = -1; |
| |
| tdf_ = ExpTupleDesc::UNINITIALIZED_FORMAT; |
| alignment_ = 1; // no alignment |
| |
| defClass_ = NO_DEFAULT; |
| defaultValue_ = 0; |
| defaultFieldNum_ = 0x0ffff ; // initialize to an invalid field num |
| |
| flags_ = 0; |
| flags2_ = 0; |
| |
| if (!complex_type) |
| setClassID(SimpleTypeID); |
| else { |
| flags_ |= COMPLEX_TYPE; |
| |
| setClassID(ComplexTypeID); |
| } |
| setBulkMoveable(TRUE); |
| |
| str_pad(fillers_, sizeof(fillers_), '\0'); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // This method returns the virtual function table pointer for an object |
| // with the given class ID; used by NAVersionedObject::driveUnpack(). |
| // ----------------------------------------------------------------------- |
| char *Attributes::findVTblPtr(short classID) |
| { |
| char *vtblPtr; |
| switch (classID) |
| { |
| case ShowplanID: |
| GetVTblPtr(vtblPtr, ShowplanAttributes); |
| break; |
| case SimpleTypeID: |
| GetVTblPtr(vtblPtr, SimpleType); |
| break; |
| case BigNumID: |
| GetVTblPtr(vtblPtr, BigNum); |
| break; |
| case ComplexTypeID: |
| default: |
| GetVTblPtr(vtblPtr, ComplexType); |
| break; |
| } |
| return vtblPtr; |
| } |
| |
| Long Attributes::pack(void * space) |
| { |
| defaultValue_.pack(space); |
| |
| return NAVersionedObject::pack(space); |
| } |
| |
| Lng32 Attributes::unpack(void * base, void * reallocator) |
| { |
| if (defaultValue_.unpack(base)) return -1; |
| return NAVersionedObject::unpack(base, reallocator); |
| } |
| |
| void Attributes::fixup(Space * /*space*/, |
| char * constantsArea, |
| char * tempsArea, |
| char * persistentArea, |
| short fixupConstsAndTemps, |
| NABoolean spaceCompOnly) |
| { |
| if ((! fixupConstsAndTemps) || (spaceCompOnly)) |
| return; |
| |
| char *area; |
| |
| if ((atp_ == 0) && (atpindex_ == 0)) |
| area = constantsArea; |
| else if((atp_ == 0) && (atpindex_ == 1)) |
| area = tempsArea; |
| else if((atp_ == 1) && (atpindex_ == 1)) |
| area = persistentArea; |
| else |
| return; |
| |
| #if 1 |
| assert( area == (char *)0 ); |
| |
| #else /* FOLLOWING CODE SHOULD NOT BE NEEDED */ |
| offset_ = (uLong)(area + offset_); |
| if (getNullFlag()) // nullable |
| nullIndOffset_ = (ULng32)(area + nullIndOffset_); |
| if (getVCIndicatorLength() > 0) |
| vcLenIndOffset_ = (ULng32)(area + vcLenIndOffset_); |
| #endif |
| |
| } |
| |
| char * getDatatypeAsString(Int32 datatype, NABoolean extFormat = false ) |
| { |
| switch (datatype) |
| { |
| // When you add new datatype in /common/dfs2rec.h, don't |
| // forget add new case here. Otherwise, showplan won't display it. |
| |
| case REC_BIN8_SIGNED: return extFormat? (char *)"TINYINT SIGNED":(char *)"REC_BIN8_SIGNED"; |
| case REC_BIN8_UNSIGNED: return extFormat? (char *)"TINYINT UNSIGNED":(char *)"REC_BIN8_UNSIGNED"; |
| case REC_BIN16_SIGNED: return extFormat? (char *)"SMALLINT SIGNED":(char *)"REC_BIN16_SIGNED"; |
| case REC_BIN16_UNSIGNED: return extFormat? (char *)"SMALLINT UNSIGNED":(char *)"REC_BIN16_UNSIGNED"; |
| case REC_BIN32_SIGNED: return extFormat? (char *)"INTEGER SIGNED":(char *)"REC_BIN32_SIGNED"; |
| case REC_BIN32_UNSIGNED: return extFormat? (char *)"INTEGER UNSIGNED":(char *)"REC_BIN32_UNSIGNED"; |
| case REC_BIN64_SIGNED: return extFormat? (char *)"LARGEINT":(char *)"REC_BIN64_SIGNED"; |
| case REC_BIN64_UNSIGNED: return extFormat? (char *)"LARGEINT UNSIGNED":(char *)"REC_BIN64_UNSIGNED"; |
| case REC_BPINT_UNSIGNED: return extFormat? (char *)"BIT PRECISION INTEGER":(char *)"REC_BPINT_UNSIGNED"; |
| |
| case REC_IEEE_FLOAT32: return extFormat? (char *)"IEEE FLOAT":(char *)"REC_IEEE_FLOAT32"; |
| case REC_IEEE_FLOAT64: return extFormat? (char *)"IEEE DOUBLE PRECISION":(char *)"REC_IEEE_FLOAT64"; |
| |
| case REC_DECIMAL_UNSIGNED: return extFormat? (char *)"DECIMAL UNSIGNED":(char *)"REC_DECIMAL_UNSIGNED"; |
| case REC_DECIMAL_LS: return extFormat? (char *)"DECIMAL SIGNED":(char *)"REC_DECIMAL_LS"; |
| case REC_DECIMAL_LSE: return extFormat? (char *)"DECIMAL SIGNED":(char *)"REC_DECIMAL_LSE"; |
| case REC_NUM_BIG_UNSIGNED: return extFormat? (char *)"NUMERIC":(char *)"REC_NUM_BIG_UNSIGNED"; |
| case REC_NUM_BIG_SIGNED: return extFormat? (char *)"NUMERIC":(char *)"REC_NUM_BIG_SIGNED"; |
| |
| case REC_BYTE_F_ASCII: return extFormat? (char *)"CHAR":(char *)"REC_BYTE_F_ASCII"; |
| case REC_NCHAR_F_UNICODE: return extFormat? (char *)"NCHAR":(char *)"REC_NCHAR_F_UNICODE"; |
| |
| case REC_BYTE_V_ASCII: return extFormat? (char *)"VARCHAR":(char *)"REC_BYTE_V_ASCII"; |
| case REC_NCHAR_V_UNICODE: return extFormat? (char *)"NCHAR VARYING":(char *)"REC_NCHAR_V_UNICODE"; |
| case REC_BYTE_V_ASCII_LONG: return extFormat? (char *)"VARCHAR":(char *)"REC_BYTE_V_ASCII_LONG"; |
| |
| case REC_BYTE_V_ANSI: return extFormat? (char *)"VARCHAR":(char *)"REC_BYTE_V_ANSI"; |
| case REC_BYTE_V_ANSI_DOUBLE: return extFormat? (char *)"VARCHAR":(char *)"REC_BYTE_V_ANSI_DOUBLE"; |
| |
| case REC_SBYTE_LOCALE_F: return extFormat? (char *)"CHAR":(char *)"REC_SBYTE_LOCALE_F"; |
| case REC_MBYTE_LOCALE_F: return extFormat? (char *)"CHAR":(char *)"REC_MBYTE_LOCALE_F"; |
| case REC_MBYTE_F_SJIS: return extFormat? (char *)"CHAR":(char *)"REC_MBYTE_F_SJIS"; |
| case REC_MBYTE_V_SJIS: return extFormat? (char *)"VARCHAR":(char *)"REC_MBYTE_V_SJIS"; |
| |
| case REC_DATETIME: return extFormat? (char *)"DATETIME":(char *)"REC_DATETIME"; |
| |
| case REC_INT_YEAR: return extFormat? (char *)"INTERVAL YEAR":(char *)"REC_INT_YEAR"; |
| case REC_INT_MONTH: return extFormat? (char *)"INTERVAL MONTH":(char *)"REC_INT_MONTH"; |
| case REC_INT_YEAR_MONTH: return extFormat? (char *)"INTERVAL YEAR TO MONTH":(char *)"REC_INT_YEAR_MONTH"; |
| case REC_INT_DAY: return extFormat? (char *)"INTERVAL DAY":(char *)"REC_INT_DAY"; |
| case REC_INT_HOUR: return extFormat? (char *)"INTERVAL HOUR":(char *)"REC_INT_HOUR"; |
| case REC_INT_DAY_HOUR: return extFormat? (char *)"INTERVAL DAY TO HOUR":(char *)"REC_INT_DAY_HOUR"; |
| case REC_INT_MINUTE: return extFormat? (char *)"INTERVAL MINUTE":(char *)"REC_INT_MINUTE"; |
| case REC_INT_HOUR_MINUTE: return extFormat? (char *)"INTERVAL HOUR TO MINUTE":(char *)"REC_INT_HOUR_MINUTE"; |
| case REC_INT_DAY_MINUTE: return extFormat? (char *)"INTERVAL DAY TO MINUTE":(char *)"REC_INT_DAY_MINUTE"; |
| case REC_INT_SECOND: return extFormat? (char *)"INTERVAL SECOND":(char *)"REC_INT_SECOND"; |
| case REC_INT_MINUTE_SECOND: return extFormat? (char *)"INTERVAL MINUTE TO SECOND":(char *)"REC_INT_MINUTE_SECOND"; |
| case REC_INT_HOUR_SECOND: return extFormat? (char *)"INTERVAL HOUR TO SECOND":(char *)"REC_INT_HOUR_SECOND"; |
| case REC_INT_DAY_SECOND: return extFormat? (char *)"INTERVAL DAY TO SECOND":(char *)"REC_INT_DAY_SECOND"; |
| case REC_INT_FRACTION: return extFormat? (char *)"INTERVAL FRACTION":(char *)"REC_INT_FRACTION"; |
| case REC_BLOB: return extFormat? (char *)"BLOB":(char *)"REC_BLOB"; |
| case REC_CLOB: return extFormat? (char *)"CLOB":(char *)"REC_CLOB"; |
| case REC_BOOLEAN: return extFormat ? (char *)"BOOLEAN" : (char *)"REC_BOOLEAN"; |
| |
| // When you add new datatype in /common/dfs2rec.h, don't |
| // forget add new case here. Otherwise, showplan won't display it. |
| default: return extFormat? (char *)"UNKNOWN":(char *)"add datatype in getDatatypeAsString()"; |
| } |
| } |
| |
| ShowplanAttributes::ShowplanAttributes(Lng32 valueId, char * text) |
| { |
| setClassID(ShowplanID); |
| valueId_ = valueId; |
| if (text) |
| { |
| if (str_len(text) < sizeof(text_)) |
| str_cpy(text_, text, str_len(text)+1,'\0'); |
| else |
| { |
| memset(text_, 0, sizeof(text_)); |
| str_cpy_all(text_, text, sizeof(text_) - 4); |
| str_cat(text_, " ...",text_); |
| } |
| } |
| else |
| text_[0] = 0; |
| |
| memset(fillers_, 0, sizeof(fillers_)); |
| } |
| |
| ShowplanAttributes::~ShowplanAttributes() |
| {} |
| |
| Attributes * ShowplanAttributes::newCopy() |
| { |
| ShowplanAttributes * new_copy = new ShowplanAttributes(valueId(), text()); |
| *new_copy = *this; |
| return new_copy; |
| } |
| |
| Attributes * ShowplanAttributes::newCopy(CollHeap * heap) |
| { |
| ShowplanAttributes * new_copy = new(heap) ShowplanAttributes(valueId(), text()); |
| *new_copy = *this; |
| return new_copy; |
| } |
| |
| void Attributes::displayContents(Space * space, Int32 operandNum, |
| char * constsArea, Attributes * spAttr) |
| { |
| char buf[250]; |
| char r[15]; |
| |
| if (operandNum == 0) |
| str_cpy(r, " (result)",str_len(" (result)")+1,'\0'); |
| else |
| r[0] = 0; |
| |
| str_sprintf(buf, " Operand #%d%s:", operandNum, r); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| str_sprintf(buf, " Datatype = %s(%d), Length = %d, Null Flag = %d", |
| getDatatypeAsString(getDatatype()), getDatatype(), getLength(), getNullFlag()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| if ((getDatatype() == REC_BLOB) || |
| (getDatatype() == REC_CLOB)) |
| { |
| |
| |
| Int64 ll = getLength(); |
| if (isLengthInKB()) |
| ll = ll*1024; |
| // Int64 ll = (Int64)getPrecision() * 1000 + (Int64)getScale(); |
| str_sprintf(buf, " LobLength = %ld bytes", ll); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| |
| str_sprintf(buf, " Precision = %d, Scale = %d, Collation = %d, flags_ = %x", |
| getPrecision(), getScale(), getCollation(), flags_); |
| |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| str_cpy(buf, " Tuple Data Format = ", |
| str_len(" Tuple Data Format = ")+1,'\0'); |
| |
| switch (getTupleFormat()) |
| { |
| case ExpTupleDesc::UNINITIALIZED_FORMAT: |
| str_cat(buf, "UNINITIALIZED_FORMAT", buf); |
| break; |
| |
| case ExpTupleDesc::PACKED_FORMAT: |
| str_cat(buf, "PACKED_FORMAT", buf); |
| break; |
| |
| case ExpTupleDesc::SQLMX_KEY_FORMAT: |
| str_cat(buf, "SQLMX_KEY_FORMAT", buf); |
| break; |
| |
| case ExpTupleDesc::SQLARK_EXPLODED_FORMAT: |
| str_cat(buf, "SQLARK_EXPLODED_FORMAT", buf); |
| break; |
| |
| case ExpTupleDesc::SQLMX_FORMAT: |
| str_cat(buf, "SQLMX_FORMAT", buf); |
| break; |
| |
| case ExpTupleDesc::SQLMX_ALIGNED_FORMAT: |
| str_cat(buf, "SQLMX_ALIGNED_FORMAT", buf); |
| break; |
| |
| default: |
| str_cat(buf, "Unrecognized format", buf); |
| break; |
| |
| } // switch tuple format |
| |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| if (isAddedCol()) |
| { |
| str_sprintf(buf, " DefaultFieldNum = %d",getDefaultFieldNum()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| |
| char constOrTemp[150]; |
| if ((getAtp()) == 0 && (getAtpIndex() == 0)) |
| { |
| str_cpy(constOrTemp, " (Constant)", |
| str_len(" (Constant)")+1,'\0'); |
| } |
| else if ((getAtp() == 0) && (getAtpIndex() == 1)) |
| str_cpy(constOrTemp, " (Temporary)", |
| str_len(" (Temporary)")+1,'\0'); |
| else if ((getAtp() == 1) && (getAtpIndex() == 1)) |
| str_cpy(constOrTemp, " (Persistent)", |
| str_len(" (Persistent)")+1,'\0'); |
| else if (getAtpIndex() == 0) |
| str_cpy(constOrTemp, " !!!ERROR!!! - Invalid (Atp,AtpIndex)", |
| str_len(" !!!ERROR!!! - Invalid (Atp,AtpIndex)")+1,'\0'); |
| else |
| str_cpy(constOrTemp, " ", str_len(" ")+1,'\0'); |
| |
| str_sprintf(buf, " Atp = %d, AtpIndex = %d%s", |
| getAtp(), getAtpIndex(), constOrTemp); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| str_sprintf(buf, " Offset = %d, NullIndOffset = %d, VClenIndOffset = %d", |
| (getOffset() == ExpOffsetMax ? -1 : (Lng32)getOffset()), |
| (getNullIndOffset() == ExpOffsetMax ? -1 : getNullIndOffset()), |
| (getVCLenIndOffset() == ExpOffsetMax ? -1 : getVCLenIndOffset())); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| if ((getTupleFormat() == ExpTupleDesc::SQLMX_FORMAT) || |
| (getTupleFormat() == ExpTupleDesc::SQLMX_ALIGNED_FORMAT)) |
| { |
| str_sprintf(buf, " RelOffset = %d, VoaOffset = %d, NullBitIdx = %d", |
| getRelOffset(), |
| (getVoaOffset() == ExpOffsetMax ? -1 : getVoaOffset()), |
| getNullBitIndex()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| |
| str_sprintf(buf, " NullIndLength = %d, VClenIndLength = %d", |
| getNullIndicatorLength(), getVCIndicatorLength()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| |
| if ((getRowsetSize() > 0) || |
| (getRowsetInfo())) |
| { |
| str_sprintf(buf, " rowsetSize_ = %d, rowsetInfo_ = %x", |
| getRowsetSize(), getRowsetInfo()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| |
| if (spAttr) |
| { |
| str_sprintf(buf, " ValueId = %d", |
| ((ShowplanAttributes *)spAttr)->valueId()); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| str_sprintf(buf, " Text = %s", |
| (((ShowplanAttributes *)spAttr)->text() ? |
| ((ShowplanAttributes *)spAttr)->text() : "")); |
| space->allocateAndCopyToAlignedSpace(buf, str_len(buf), sizeof(short)); |
| } |
| } |
| |
| ExpDatetime * |
| Attributes::castToExpDatetime() |
| { |
| return NULL; |
| } |
| |
| // --------------------------------------------------------------------- |
| // Method for comparing if two Attributes are equal. |
| // --------------------------------------------------------------------- |
| NABoolean Attributes::operator==(const Attributes& other) const |
| { |
| Attributes thisAttr = (Attributes&)(*this); // to make 'this' a non-const |
| Attributes otherAttr = (Attributes&)other; |
| |
| if (datatype_ == otherAttr.datatype_ && |
| nullFlag_ == otherAttr.nullFlag_ && |
| defClass_ == otherAttr.defClass_ && |
| (thisAttr.upshift() == otherAttr.upshift()) && |
| tdf_ == otherAttr.tdf_ && |
| ( (alignment_ > 0 && otherAttr.alignment_ > 0) |
| ? (alignment_ == otherAttr.alignment_ ) : TRUE ) && |
| ( (nullFlag_ != 0) |
| ? (nullIndicatorLength_ == otherAttr.nullIndicatorLength_ && |
| vcIndicatorLength_ == otherAttr.vcIndicatorLength_ ) : TRUE) |
| ) |
| return TRUE; |
| else |
| return FALSE; |
| } |
| |
| NABoolean SimpleType::operator==(const Attributes& other) const |
| { |
| if (Attributes::operator==(other)) |
| { |
| SimpleType thisAttr = (SimpleType&)(*this); |
| SimpleType otherAttr = (SimpleType&)other; |
| |
| if (length_ == otherAttr.length_ && |
| precision_ == otherAttr.precision_ && |
| (DFS2REC::isAnyCharacter(thisAttr.getDatatype()) |
| ? (thisAttr.getCharSet() == otherAttr.getCharSet()) |
| : (scale_ == otherAttr.scale_)) && |
| ((thisAttr.getDefaultClass() == DEFAULT_NULL || |
| thisAttr.getDefaultClass() == NO_DEFAULT || |
| thisAttr.getDefaultClass() == DEFAULT_UUID || |
| thisAttr.getDefaultClass() == DEFAULT_CURRENT_UT || |
| thisAttr.getDefaultClass() == DEFAULT_CURRENT) || |
| (thisAttr.getDefaultValue() && otherAttr.getDefaultValue() && |
| (str_cmp(thisAttr.getDefaultValue(), |
| otherAttr.getDefaultValue(), |
| (thisAttr.getNullIndicatorLength() + |
| thisAttr.getVCIndicatorLength() + |
| length_) ) == 0) |
| ) ) |
| ) |
| return TRUE; |
| else |
| return FALSE; |
| } |
| else |
| return FALSE; |
| } |
| |
| NABoolean ComplexType::operator==(const Attributes& other) const |
| { |
| if (Attributes::operator==(other)) |
| { |
| ComplexType &thisAttr = (ComplexType&)(*this); |
| ComplexType &otherAttr = (ComplexType&)other; |
| |
| if ((thisAttr.complexDatatype_ == otherAttr.complexDatatype_) && |
| (thisAttr.getLength() == otherAttr.getLength()) && |
| (thisAttr.getPrecision() == otherAttr.getPrecision()) && |
| (thisAttr.getScale() == otherAttr.getScale())) |
| return TRUE; |
| else |
| return FALSE; |
| } |
| else |
| return FALSE; |
| } |
| |
| NABoolean isAddedColumn(Attributes * srcAttr, |
| NABoolean tableHasAddedColumns, |
| NABoolean tableHasVariableColumns, |
| ULng32 offsetOfFirstFixedFieldInRec, |
| ULng32 recordLength, |
| char * recordPtr |
| ) |
| { |
| // Check if this is an added column. |
| // There are 4 cases to check for: |
| // (1) The column is a variable column and the offset to the first |
| // fixed field is greater than the offset |
| // to VOA entry for this column. |
| // (2) This is a fixed column and its offset is greater than the |
| // length of the row in, and there are no varchar |
| // columns in the roq |
| // (3) This is a fixed column and its offset is greater than |
| // the offset for the first variable length column in the audit |
| // row image. |
| // (4) This is a fixed column, but there are no previous fixed fields |
| // in the row |
| if (((srcAttr->isAddedCol()) || (tableHasAddedColumns)) && |
| (((srcAttr->getVCIndicatorLength() > 0) && |
| (srcAttr->getVoaOffset() >= offsetOfFirstFixedFieldInRec)) || |
| (((!tableHasVariableColumns) && |
| ((offsetOfFirstFixedFieldInRec + srcAttr->getRelOffset()) >= |
| recordLength)) || |
| ((tableHasVariableColumns) && |
| ((offsetOfFirstFixedFieldInRec + srcAttr->getRelOffset()) >= |
| *(ULng32 *)(recordPtr + sizeof(Lng32)))) || |
| (tableHasVariableColumns && |
| (srcAttr->getVCIndicatorLength() == 0) && |
| ((offsetOfFirstFixedFieldInRec == sizeof(Lng32)) || |
| (offsetOfFirstFixedFieldInRec == 0)))))) |
| return TRUE; |
| |
| return FALSE; |
| } |
| |
| // Return number of bytes of the first character in buf. SJIS should be 1 or |
| // 2. UTF8 should be 1 to 4 (byte). UCS2 is 1 (we use wchar for UCS2 data. So |
| // it is 1, not 2). |
| Int32 Attributes::getFirstCharLength(const char *buf, |
| Int32 buflen, |
| CharInfo::CharSet cs) |
| { |
| UInt32 UCS4value; |
| UInt32 firstCharLenInBuf; |
| |
| // The buffer explain send to string function includes character 0, |
| // treat it as single byte character. |
| if( cs == CharInfo::ISO88591 || |
| cs == CharInfo::UCS2 || |
| buf[0] == 0) |
| { |
| firstCharLenInBuf = 1; |
| } |
| else |
| { |
| firstCharLenInBuf = |
| LocaleCharToUCS4(buf, buflen, &UCS4value, convertCharsetEnum(cs)); |
| } |
| return firstCharLenInBuf; |
| } |
| |
| // Find the number of character at the offset in buf. |
| Int32 Attributes::convertOffsetToChar(const char *buf, |
| Int32 offset, |
| CharInfo::CharSet cs) |
| { |
| if (cs == CharInfo::ISO88591 || cs == CharInfo::UCS2) |
| return(offset); |
| |
| Int32 firstCharLenInBuf; |
| UInt32 UCS4value; |
| |
| cnv_charset charset = convertCharsetEnum(cs); |
| |
| Int32 numberOfChar = 0; |
| Int32 i = 0; |
| |
| while(i < offset) |
| { |
| firstCharLenInBuf = LocaleCharToUCS4(&buf[i], |
| offset - i, |
| &UCS4value, |
| charset); |
| if(firstCharLenInBuf < 0) return firstCharLenInBuf; |
| |
| i += firstCharLenInBuf; |
| ++numberOfChar; |
| } |
| return numberOfChar; |
| } |
| |
| // Return number of bytes used by the characters in buf preceding the Nth char. |
| // Return an error if we encounter a character that is not valid in the cs |
| // character set. |
| Int32 Attributes::convertCharToOffset (const char *buf, |
| Int32 numOfChar, |
| Int32 maxBufLen, |
| CharInfo::CharSet cs) |
| { |
| if (cs == CharInfo::ISO88591 || cs == CharInfo::UCS2) |
| return((numOfChar <= maxBufLen) ? numOfChar - 1 : maxBufLen); |
| |
| Int32 firstCharLenInBuf; |
| UInt32 UCS4value; |
| |
| cnv_charset charset = convertCharsetEnum(cs); |
| |
| // Number of character in string functions start from 1, not 0. 1 means |
| // the first character in the string. Offset start from 0. The offset of |
| // the first character in a string is 0. |
| Int32 count = 1; |
| Int32 offset = 0; |
| |
| while(count < numOfChar && offset < maxBufLen) |
| { |
| firstCharLenInBuf = LocaleCharToUCS4(&buf[offset], |
| maxBufLen - offset, |
| &UCS4value, |
| charset); |
| |
| if(firstCharLenInBuf < 0) return firstCharLenInBuf; |
| |
| offset += firstCharLenInBuf; |
| ++count; |
| } |
| return offset; |
| } |
| |
| Int32 Attributes::getCharLengthInBuf |
| (const char *buf, |
| const char *endOfBuf, |
| char *charLengthInBuf, |
| CharInfo::CharSet cs) |
| { |
| Int32 numberOfCharacterInBuf; |
| |
| if (cs == CharInfo::ISO88591 || cs == CharInfo::UCS2) |
| { |
| numberOfCharacterInBuf = endOfBuf - buf; |
| if(charLengthInBuf != NULL) |
| { |
| for(Int32 i = 0; i < numberOfCharacterInBuf; i ++) |
| charLengthInBuf[i] = 1; |
| } |
| return numberOfCharacterInBuf; |
| } |
| |
| Int32 firstCharLenInBuf; |
| UInt32 UCS4value; |
| cnv_charset charset = convertCharsetEnum(cs); |
| |
| // For SJIS, it is impossible to get the length of the last character |
| // from right. Scan the string from the beginning and save the vales to |
| // an array. |
| // For example: SJIS string (x'5182828251') and (x'51828251'), the last |
| // character in the first string is 2-byte, double-byte "2". The last |
| // character in the second string is 1 byte, single-byte "Q". |
| |
| size_t len = endOfBuf - buf; |
| numberOfCharacterInBuf = 0; |
| |
| while(len > 0) |
| { |
| firstCharLenInBuf = LocaleCharToUCS4 (buf, len, &UCS4value, charset); |
| |
| if (firstCharLenInBuf <= 0) |
| return CNV_ERR_INVALID_CHAR; |
| else |
| { |
| if(charLengthInBuf != NULL) |
| { |
| charLengthInBuf[numberOfCharacterInBuf] = (char)firstCharLenInBuf; |
| } |
| |
| numberOfCharacterInBuf++; |
| buf += firstCharLenInBuf; |
| len -= firstCharLenInBuf; |
| } |
| } |
| return numberOfCharacterInBuf; |
| } |
| |
| Int32 Attributes::trimFillerSpaces |
| (const char* buf, Int32 precision, Int32 maxBufLen, CharInfo::CharSet cs) |
| { |
| #if 0 /* All callers have already checked this for speed reasons. May need this if SJIS supported later. */ |
| if (cs == CharInfo::UTF8) |
| #endif |
| { |
| if ( precision > 0 ) |
| { |
| Int32 endOff = lightValidateUTF8Str(buf, maxBufLen, precision, FALSE); |
| if (endOff >= 0) // If no error |
| return (endOff); |
| // else bad UTF8 chars will get detected later by caller |
| } |
| } |
| return (maxBufLen); |
| } |