| /********************************************************************** |
| // @@@ 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: GenItemFunc.C |
| * Description: Function expressions |
| * |
| * |
| * Created: 5/17/94 |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ****************************************************************************** |
| */ |
| |
| ///////////////////////////////////////////////////////////////////// |
| // |
| // Contents: |
| // |
| // BuiltinFunction::codeGen() |
| // Case::codeGen() |
| // Cast::codeGen() |
| // RaiseError::codeGen() |
| // CompEncode::codeGen() |
| // Hash::codeGen() |
| // HashComb::codeGen() |
| // HashDistPartHash::codeGen() |
| // HashDistPartHashComb::codeGen() |
| // HiveHash::codeGen() |
| // HiveHashComb::codeGen() |
| // Trim::codeGen |
| // Tup::codeGen |
| // UDFunction::codeGen() |
| // |
| ////////////////////////////////////////////////////////////////////// |
| |
| #include "Generator.h" |
| #include "GenExpGenerator.h" |
| #include "exp_function.h" |
| #include "ExpLOB.h" |
| #include "exp_datetime.h" |
| #include "exp_math_func.h" |
| #include "CharType.h" |
| #include "NumericType.h" |
| #include "RelMisc.h" |
| #include "ItemFuncUDF.h" |
| |
| short BuiltinFunction::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = 0; |
| |
| switch (getOperatorType()) |
| { |
| case ITM_CONVERTTOBITS: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionBitOper(getOperatorType(), |
| (1+getArity()), |
| attr, space); |
| } |
| break; |
| case ITM_REGEXP: |
| { |
| function_clause = |
| new(generator->getSpace()) ExRegexpClauseChar(getOperatorType(), (1+getArity()), |
| attr, space); |
| } |
| break; |
| case ITM_LIKE: |
| { |
| |
| const CharType& likeSource = |
| (CharType&)((child(0)->getValueId()).getType()); |
| |
| const CharType& likePattern = |
| (CharType&)((child(1)->getValueId()).getType()); |
| |
| switch ( likeSource.getCharSet() ) |
| { |
| case CharInfo::ISO88591: |
| case CharInfo::UTF8: |
| // case CharInfo::SJIS: // Uncomment this if we ever support SJIS |
| function_clause = |
| new(generator->getSpace()) ex_like_clause_char(getOperatorType() |
| ,1+getArity() |
| ,attr |
| ,space |
| ); |
| |
| // Consider generating pcode for this. Certain criteria must be |
| // met, however. If pattern string is a constant, with no escape |
| // characters, and we're dealing with a fixed-length string (should |
| // be see constants are exploded), then we met the minimum criteria. |
| // Pcode generation for LIKE will do other checks. |
| |
| if ((child(1)->castToItemExpr()->getOperatorType() == ITM_CONSTANT)&& |
| (likePattern.getFSDatatype() == REC_BYTE_F_ASCII) && |
| (getArity() <= 2)) |
| { |
| char* pat = (char*) |
| ((ConstValue*)(child(1)->castToItemExpr()))->getConstValue(); |
| |
| // Pass in constant string for analysis during pcode generation. |
| ((ex_like_clause_base*)(function_clause))->setPatternStr(pat); |
| } |
| else |
| function_clause->setNoPCodeAvailable(TRUE); |
| |
| break; |
| case CharInfo::UCS2: |
| function_clause = new(generator->getSpace()) |
| ex_like_clause_doublebyte(ITM_LIKE_DOUBLEBYTE |
| ,1+getArity() |
| ,attr |
| ,space |
| ); |
| break; |
| default: |
| GenAssert(0, "unknown value for bytes-per-char."); |
| } |
| } |
| |
| break; |
| |
| case ITM_SLEEP: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_sleep(getOperatorType(),(1+getArity()), |
| attr, space); |
| } |
| |
| break; |
| case ITM_UNIX_TIMESTAMP: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_unixtime(getOperatorType(), (1+getArity()), |
| attr, space); |
| } |
| |
| break; |
| case ITM_CURRENT_TIMESTAMP: |
| case ITM_CURRENT_TIMESTAMP_RUNNING: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_current(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| // MV, |
| case ITM_CURRENTEPOCH: |
| case ITM_VSBBROWTYPE: |
| case ITM_VSBBROWCOUNT: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionGenericUpdateOutput(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| // ++ Triggers - |
| case ITM_INTERNALTIMESTAMP: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionInternalTimestamp(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_UNIQUE_EXECUTE_ID: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_unique_execute_id(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_GET_TRIGGERS_STATUS: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_get_triggers_status(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_GET_BIT_VALUE_AT: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_get_bit_value_at(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| // -- Triggers - |
| |
| case ITM_IS_BITWISE_AND_TRUE: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_is_bitwise_and_true(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_SHA1: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionSha(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_SHA2_256: |
| case ITM_SHA2_224: |
| case ITM_SHA2_384: |
| case ITM_SHA2_512: |
| { |
| Lng32 mode = 0; |
| switch (getOperatorType()) { |
| case ITM_SHA2_256: |
| mode = 256; |
| break; |
| |
| case ITM_SHA2_224: |
| mode = 224; |
| break; |
| |
| case ITM_SHA2_384: |
| mode = 384; |
| break; |
| |
| case ITM_SHA2_512: |
| mode = 512; |
| break; |
| } |
| function_clause = |
| new(generator->getSpace()) ExFunctionSha2(getOperatorType(), |
| attr, space, mode); |
| } |
| |
| break; |
| |
| case ITM_MD5: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionMd5(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_CRC32: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionCrc32(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_ISIPV4: |
| case ITM_ISIPV6: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionIsIP(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| case ITM_INET_ATON: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionInetAton(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_INET_NTOA: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionInetNtoa(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| // -- MV |
| case ITM_CONCAT: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_concat(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_SUBSTR: |
| { |
| |
| if (getValueId().getType().isLob()) |
| { |
| function_clause = new(generator->getSpace()) |
| ExpLOBfuncSubstring(getOperatorType(), |
| (1+getArity()), attr, space); |
| break; |
| } |
| |
| |
| const CharType& substringOperandType = |
| (CharType&)((child(0)->getValueId()).getType()); |
| |
| switch ( substringOperandType.getCharSet() ) |
| { |
| case CharInfo::ISO88591: |
| case CharInfo::UTF8: |
| // case CharInfo::SJIS: // Uncomment this if we ever support SJIS |
| function_clause = new(generator->getSpace()) |
| ex_function_substring(getOperatorType(), |
| (1+getArity()), attr, space); |
| break; |
| |
| case CharInfo::UCS2: |
| function_clause = new(generator->getSpace()) |
| ex_function_substring_doublebyte(ITM_SUBSTR_DOUBLEBYTE, |
| (1+getArity()), attr, space |
| ); |
| break; |
| |
| default: |
| GenAssert(0, "unknown value for bytes-per-char."); |
| } |
| } |
| |
| break; |
| |
| case ITM_LOWER: |
| { |
| const CharType& lowerOperandType = |
| (CharType&)((child(0)->getValueId()).getType()); |
| |
| if ( lowerOperandType.getCharSet() != CharInfo::UNICODE ) |
| function_clause = new(generator->getSpace()) |
| ex_function_lower(getOperatorType(), attr, space); |
| else |
| function_clause = new(generator->getSpace()) |
| ex_function_lower_unicode(ITM_LOWER_UNICODE, attr, space); |
| } |
| |
| break; |
| |
| case ITM_UPPER: |
| { |
| const CharType& upperOperandType = |
| (CharType&)((child(0)->getValueId()).getType()); |
| |
| if ( upperOperandType.getCharSet() != CharInfo::UNICODE ) |
| function_clause = new(generator->getSpace()) |
| ex_function_upper(ITM_UPPER, attr, space); |
| else |
| function_clause = new(generator->getSpace()) |
| ex_function_upper_unicode(ITM_UPPER_UNICODE, attr, space); |
| } |
| |
| break; |
| |
| case ITM_CHAR_LENGTH: |
| { |
| |
| const CharType& charLenOperandType = |
| (CharType&)(child(0)->getValueId().getType()); |
| |
| switch ( charLenOperandType.getCharSet() ) |
| { |
| case CharInfo::ISO88591: |
| case CharInfo::UTF8: |
| // case CharInfo::SJIS: // Uncomment this if we ever support SJIS |
| function_clause = new(generator->getSpace()) |
| ex_function_char_length(ITM_CHAR_LENGTH, attr, space); |
| break; |
| case CharInfo::UCS2: |
| function_clause = new(generator->getSpace()) |
| ex_function_char_length_doublebyte(ITM_CHAR_LENGTH_DOUBLEBYTE, |
| attr, space); |
| break; |
| default: |
| GenAssert(0, "unknown value for bytes-per-char."); |
| } |
| } |
| |
| break; |
| |
| case ITM_OCTET_LENGTH: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_oct_length(getOperatorType(), |
| attr, space); |
| } |
| |
| break; |
| |
| case ITM_POSITION: |
| { |
| const CharType& patternOperandType = |
| (CharType&)(child(0)->getValueId().getType()); |
| |
| switch ( patternOperandType.getCharSet() ) |
| { |
| case CharInfo::ISO88591: |
| case CharInfo::UTF8: |
| // case CharInfo::SJIS: // Uncomment this if we ever support SJIS |
| function_clause = new(generator->getSpace()) |
| ex_function_position(ITM_POSITION, attr, space, |
| (getArity() + 1)); |
| |
| ((ex_function_position *)function_clause)->setCollation(((PositionFunc*)this)->getCollation()); |
| |
| break; |
| |
| case CharInfo::UCS2: |
| function_clause = new(generator->getSpace()) |
| ex_function_position_doublebyte(ITM_POSITION_DOUBLEBYTE, attr, space, |
| (getArity() + 1)); |
| |
| break; |
| |
| default: |
| GenAssert(0, "unknown value for bytes-per-char."); |
| } |
| } |
| |
| break; |
| |
| case ITM_REPLACE: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionReplace(getOperatorType(), |
| attr, space); |
| |
| const NAType &type1 = |
| child(0)->castToItemExpr()->getValueId().getType(); |
| const NAType &type2 = |
| child(1)->castToItemExpr()->getValueId().getType(); |
| const NAType &type3 = |
| child(2)->castToItemExpr()->getValueId().getType(); |
| |
| if ((type1.getTypeQualifier() == NA_CHARACTER_TYPE) && |
| (type2.getTypeQualifier() == NA_CHARACTER_TYPE)) |
| { |
| const CharType &cType1 = (CharType&)type1; |
| const CharType &cType2 = (CharType&)type2; |
| const CharType &cType3 = (CharType&)type3; |
| |
| CharInfo::Collation coll1= cType1.getCollation(); |
| CharInfo::Collation coll2= cType2.getCollation(); |
| CharInfo::Collation coll3= cType3.getCollation(); |
| |
| CMPASSERT(coll1 == coll2 && coll1 == coll3); |
| if (CollationInfo::isSystemCollation(coll1)) |
| { |
| ((ExFunctionReplace*)function_clause)->setCollation(coll1); |
| |
| Lng32 len = 0; |
| ItemExpr * tmpEncode; |
| const NAType * typ; |
| const CharType * ctyp; |
| |
| tmpEncode = |
| new(generator->wHeap()) |
| CompEncode(child(0),FALSE, -1, CollationInfo::Search); |
| |
| typ= tmpEncode->synthesizeType(); |
| ctyp = (CharType *)typ; |
| len = ctyp->getNominalSize(); |
| |
| ((ExFunctionReplace*)function_clause)->setArgEncodedLen((Int16)len, 0); |
| |
| tmpEncode = |
| new(generator->wHeap()) |
| CompEncode(child(1),FALSE, -1, CollationInfo::Search); |
| |
| typ = tmpEncode->synthesizeType(); |
| ctyp = (CharType *)typ; |
| len = ctyp->getNominalSize(); |
| |
| ((ExFunctionReplace*)function_clause)->setArgEncodedLen((Int16)len, 1); |
| |
| } |
| else |
| { |
| NABoolean doCIcomp = |
| ((cType1.isCaseinsensitive()) && (cType2.isCaseinsensitive())); |
| |
| if ((doCIcomp) && (NOT cType1.isUpshifted())) |
| ((ExFunctionReplace*)function_clause)-> |
| setCaseInsensitiveOperation(TRUE); |
| } |
| } |
| } |
| break; |
| |
| case ITM_REPEAT: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionRepeat(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_RETURN_TRUE: |
| case ITM_RETURN_FALSE: |
| case ITM_RETURN_NULL: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_bool(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_INVERSE: |
| { |
| MapInfo * inv_map_info |
| = generator->getMapInfo(getValueId()); |
| |
| MapInfo * child_map_info |
| = generator->getMapInfo(child(0)->castToItemExpr()->getValueId()); |
| |
| (inv_map_info->getAttr())->copyLocationAttrs(child_map_info->getAttr()); |
| } |
| break; |
| |
| case ITM_CONVERTTIMESTAMP: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_converttimestamp(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_DAYOFWEEK: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_dayofweek(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_JULIANTIMESTAMP: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_juliantimestamp(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_EXEC_COUNT: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_exec_count(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_CURR_TRANSID: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_curr_transid(getOperatorType(), |
| attr, space); |
| GenAssert(0, "eval method is missing for curr_transid function"); |
| } |
| break; |
| |
| case ITM_USER: |
| case ITM_USERID: |
| case ITM_AUTHNAME: |
| case ITM_AUTHTYPE: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_user(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_NULLIFZERO: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_nullifzero(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_NVL: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_nvl(getOperatorType(), |
| attr, space); |
| } |
| break; |
| case ITM_JSONOBJECTFIELDTEXT: |
| { |
| function_clause = |
| new(generator->getSpace()) ex_function_json_object_field_text(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_QUERYID_EXTRACT: |
| { |
| function_clause = |
| new(generator->getSpace()) |
| ex_function_queryid_extract(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_TOKENSTR: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionTokenStr(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_REVERSE: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionReverseStr(getOperatorType(), |
| attr, space); |
| } |
| break; |
| |
| case ITM_UNIQUE_ID: |
| case ITM_UNIQUE_ID_SYS_GUID: |
| case ITM_UNIQUE_SHORT_ID: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionUniqueId(getOperatorType(), |
| attr, |
| space); |
| } |
| break; |
| |
| case ITM_ROWNUM: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionRowNum(getOperatorType(), |
| attr, |
| space); |
| } |
| break; |
| |
| case ITM_SOUNDEX: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionSoundex(getOperatorType(), |
| attr, |
| space); |
| } |
| break; |
| |
| case ITM_AES_ENCRYPT: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionAESEncrypt(getOperatorType(), |
| attr, |
| space, |
| getArity(), |
| CmpCommon::getDefaultNumeric(BLOCK_ENCRYPTION_MODE)); |
| break; |
| } |
| |
| case ITM_AES_DECRYPT: |
| { |
| function_clause = |
| new(generator->getSpace()) ExFunctionAESDecrypt(getOperatorType(), |
| attr, |
| space, |
| getArity(), |
| CmpCommon::getDefaultNumeric(BLOCK_ENCRYPTION_MODE)); |
| break; |
| } |
| |
| case ITM_SPLIT_PART: |
| { |
| function_clause = |
| new (generator->getSpace()) ex_function_split_part(getOperatorType(), attr, space); |
| break; |
| } |
| default: |
| break; |
| } |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short Abs::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_abs(getOperatorType(), |
| attr, space); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short CharFunc::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExFunctionChar(getOperatorType(), |
| attr, space); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short CodeVal::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExFunctionAscii(getOperatorType(), |
| attr, space); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short ConvertHex::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExFunctionConvertHex(getOperatorType(), |
| attr, space); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short AggrMinMax::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_aggr_min_max_clause(getOperatorType(), |
| (short) (1+getArity()), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short AggrGrouping::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| GenAssert((rollupGroupIndex_ >= 0), |
| "AggrGrouping::codeGen. rollupGroupIndex_ must be >= 0."); |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExFunctionGrouping(getOperatorType(), |
| 1, |
| attr, |
| rollupGroupIndex_, |
| generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short AnsiUSERFunction::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = NULL; |
| |
| function_clause = |
| new(generator->getSpace()) ex_function_ansi_user(getOperatorType(), |
| attr, space); |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short BoolResult::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| child(0)->codeGen(generator); |
| |
| ItemExpr *rightMost = child(0); |
| |
| while (rightMost->getOperatorType() == ITM_ITEM_LIST) |
| rightMost = rightMost->child(1); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, 1, -1) == 1) |
| return 0; |
| |
| attr[0]->copyLocationAttrs( |
| generator->getMapInfo(rightMost->getValueId())->getAttr()); |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) bool_result_clause(getOperatorType(), |
| attr, generator->getSpace() |
| ); |
| |
| // this is the last clause. |
| function_clause->setLastClause(); |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| MapInfo * map_info = generator->addMapInfo(getValueId(), NULL); |
| map_info->codeGenerated(); |
| |
| return 0; |
| } |
| |
| short BitOperFunc::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = NULL; |
| function_clause = |
| new(generator->getSpace()) ExFunctionBitOper(getOperatorType(), |
| (1+getArity()), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short IfThenElse::codeGen(Generator *generator) { |
| return BuiltinFunction::codeGen(generator); |
| |
| // Attributes **attr; |
| // |
| // if (generator->getExpGenerator()->genItemExpr(this, &attr, 1, 0) == 1) |
| // return 0; |
| // |
| // return 0; |
| } |
| |
| short RaiseError::codeGen(Generator *generator) { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, 1 + getArity(), -1) == 1) |
| return 0; |
| |
| const char * constraintName = NULL; |
| const char * tableName = NULL; |
| const char * optionalStr = NULL; |
| |
| if (!getConstraintName().isNull()) { |
| constraintName = generator->getSpace()->AllocateAndCopyToAlignedSpace( |
| getConstraintName(), 0); |
| } |
| |
| if (!getTableName().isNull()) { |
| tableName = generator->getSpace()->AllocateAndCopyToAlignedSpace( |
| getTableName(), 0); |
| } |
| |
| if (!optionalStr_.isNull()) { |
| optionalStr = generator->getSpace()->allocateAndCopyToAlignedSpace( |
| optionalStr_.data(), optionalStr_.length(), 0); |
| } |
| |
| // make raiseError a field in this class. TBD. |
| NABoolean raiseError = ((getSQLCODE() > 0) ? TRUE : FALSE); |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExpRaiseErrorFunction (attr, |
| generator->getSpace(), |
| (raiseError ? getSQLCODE() : - getSQLCODE()), |
| raiseError, |
| constraintName, |
| tableName, |
| (getArity()==1) ? TRUE : FALSE, // -- Triggers |
| optionalStr); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short Case::codeGen(Generator * generator) |
| { |
| /////////////////////////////////////////////////////////////////// |
| // A case statement of the form: |
| // CASE CO |
| // WHEN C1 THEN R1 |
| // WHEN C2 THEN R2 |
| // ... |
| // ELSE EO |
| // END |
| // |
| // gets transformed into: |
| // CASE |
| // WHEN CO = C1 THEN R1 |
| // WHEN CO = C2 THEN R2 |
| // ... |
| // ELSE EO |
| // END |
| // |
| // If the case operand (CO) is empty, then the previous |
| // transformation is not done. Binder/Type propagator already |
| // has checked to make sure that the Ci's are in the form of |
| // a search condition. |
| // |
| // The case statement then further gets transformed into: |
| // |
| // ((CO = C1) AND (R1)) OR |
| // ((CO = C2) AND (R2)) OR |
| // ... OR |
| // (EO) |
| // |
| // This transformation evaluates the 'when' part (CO = Ci) first |
| // and if that is true, then the corresponding Ri is evaluated. |
| // The logical statement then branches out using boolean short |
| // circuit evaluation. The else part (EO) is evaluated if all |
| // when conditions fail. The location of each Ri and EO is 'fixed' up |
| // at code generation time so that they all point to the same |
| // buffer. |
| // |
| // Later, move to preCodeGen. |
| ///////////////////////////////////////////////////////////////////// |
| |
| Attributes ** attr; |
| |
| // add the case node to the map table |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, 1, 0) == 1) |
| return 0; |
| |
| Attributes * case_map_info_attr = generator->getMapInfo(getValueId())->getAttr(); |
| |
| ItemExpr * rootNode = 0; |
| |
| // Set flag indicating that a case stmt was generated |
| generator->getExpGenerator()->setCaseStmtGenerated(TRUE); |
| |
| if ( CmpCommon::getDefault(COMP_BOOL_91) == DF_OFF ) { |
| // Do the codegen for the CASE Logic here in the codegen method, |
| // rather than translating to an AND/OR tree and calling codegen |
| // on that. The advantage of this is that we can reuse the |
| // MapTable for short circuit processing. Using the AND/OR tree |
| // method can lead to excessive memory use and procesing time due |
| // to repeatedly creating and deleting map tables. |
| |
| // This code generates code in the same structure as the AND/OR |
| // method. It might be possible to generate more efficient code |
| // given the global view of the CASE statement. But for now, lets |
| // just mimic the old method. |
| |
| ValueIdList whens; |
| ValueIdList thens; |
| |
| // Collect all the WHEN and THEN clauses in lists. |
| // |
| ItemExpr *ifThenElse = child(0); |
| for (; |
| (ifThenElse != NULL) AND |
| (ifThenElse->getOperatorType() == ITM_IF_THEN_ELSE); |
| ifThenElse = ifThenElse->child(2)) |
| { |
| ItemExpr * when_part = ifThenElse->child(0); |
| ItemExpr * then_part = new(generator->wHeap()) Cast(ifThenElse->child(1), |
| &(getValueId().getType())); |
| |
| then_part->bindNode(generator->getBindWA()); |
| |
| // set the buffer location of all the convert nodes that were added |
| // in the last step to be the same as that of the case node. This |
| // will make all result values to be moved to the same location. |
| MapInfo * map_info |
| = generator->addMapInfo(then_part->getValueId(), |
| case_map_info_attr); |
| (map_info->getAttr())->copyLocationAttrs(case_map_info_attr); |
| |
| ItemExpr *caseOperand = removeCaseOperand(); |
| |
| if (caseOperand != NULL) |
| { |
| when_part = new(generator->wHeap()) BiRelat(ITM_EQUAL, caseOperand, when_part); |
| } |
| |
| // Then part must return TRUE after moving result to the proper location. |
| // It must return TRUE so that the AND/OR processing will work properly. |
| // |
| then_part = new(generator->wHeap()) BoolVal(ITM_RETURN_TRUE, then_part); |
| |
| when_part->bindNode(generator->getBindWA()); |
| then_part->bindNode(generator->getBindWA()); |
| |
| whens.insert(when_part->getValueId()); |
| thens.insert(then_part->getValueId()); |
| |
| } // for |
| |
| |
| // If there is an ELSE part, process it as one of the THEN clauses. |
| // |
| if (ifThenElse) |
| { |
| // Move the ELSE value into the same location as the THENs. |
| // |
| ItemExpr * else_part = new(generator->wHeap()) Cast(ifThenElse, |
| &(getValueId().getType())); |
| |
| else_part->bindNode(generator->getBindWA()); |
| MapInfo * map_info = |
| generator->addMapInfo(else_part->getValueId(), |
| case_map_info_attr); |
| |
| (map_info->getAttr())->copyLocationAttrs(case_map_info_attr); |
| |
| else_part = new(generator->wHeap()) BoolVal(ITM_RETURN_TRUE, else_part); |
| |
| else_part->bindNode(generator->getBindWA()); |
| |
| thens.insert(else_part->getValueId()); |
| } |
| |
| |
| // Disable the Common Expression Detection Cache. |
| // |
| generator->getExpGenerator()->incrementLevel(); |
| |
| // A MapTable used to do the Short Circuit processing of the WHEN |
| // clauses. |
| // |
| MapTable *whenscMapTable = generator->appendAtEnd(NULL); |
| |
| // A MapTable used to do the Short Circuit processing of the THEN |
| // clauses. |
| // |
| MapTable *thenscMapTable = generator->appendAtEnd(NULL); |
| MapTable *mt = generator->unlinkLast(); |
| GenAssert(mt == thenscMapTable, "Unexpected map table"); |
| |
| Space * space = generator->getSpace(); |
| |
| // Attributes for AND/OR Branching and AND/OR BiLogic. |
| // |
| Attributes ** branch_attr = new(generator->wHeap()) Attributes * [2]; |
| Attributes ** allAttr = new(generator->wHeap()) Attributes * [3]; |
| Attributes ** prevAttr = new(generator->wHeap()) Attributes * [3]; |
| |
| // Must remember previous Branch Clause. |
| // |
| ex_branch_clause *orBranchClause = NULL; |
| |
| // For all the WHEN/THEN pairs. |
| // |
| for(CollIndex i = 0; i < whens.entries(); i++) { |
| |
| ItemExpr *when_part = whens[i].getItemExpr(); |
| ItemExpr *then_part = thens[i].getItemExpr(); |
| |
| // Create an AND node and bind it. Just used to get a ValueId. |
| // Will not call codegen in this AND node. |
| // |
| ItemExpr *andNode = new(generator->wHeap()) BiLogic(ITM_AND, when_part, then_part); |
| andNode->bindNode(generator->getBindWA()); |
| |
| // Create a temporary space for the result of the AND clause. |
| MapInfo *mapInfoAndNode = |
| generator->getExpGenerator()->addTemporary(andNode->getValueId(), NULL); |
| |
| when_part->preCodeGen(generator); |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| when_part->codeGen(generator); |
| |
| // generate boolean short circuit code |
| // Add the AND Branch clause to skip the THEN if the WHEN is FALSE. |
| // |
| allAttr[0] = mapInfoAndNode->getAttr(); |
| allAttr[1] = generator->getAttr(when_part); |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| |
| branch_attr[0] = allAttr[0]->newCopy(generator->wHeap()); |
| branch_attr[0]->copyLocationAttrs(allAttr[0]); |
| |
| branch_attr[1] = allAttr[1]->newCopy(generator->wHeap()); |
| branch_attr[1]->copyLocationAttrs(allAttr[1]); |
| |
| branch_attr[0]->resetShowplan(); |
| |
| ex_branch_clause *andBranchClause |
| = new(space) ex_branch_clause(ITM_AND, branch_attr, space); |
| |
| generator->getExpGenerator()->linkClause(0, andBranchClause); |
| |
| // Use the Short Circuit Map Table when processing the THEN Clause. |
| // |
| generator->appendAtEnd(thenscMapTable); |
| then_part->preCodeGen(generator); |
| |
| // Disable the Common Expression Detection Cache. |
| // |
| generator->getExpGenerator()->incrementLevel(); |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| then_part->codeGen(generator); |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| generator->getExpGenerator()->decrementLevel(); |
| |
| ItemExpr *rightMost = then_part; |
| |
| // Find the right most part of the THEN clause. |
| // (Can this really be a list in the context of a CASE statement?) |
| // |
| while (rightMost->getOperatorType() == ITM_ITEM_LIST) |
| rightMost = rightMost->child(1)->castToItemExpr(); |
| |
| allAttr[2] = generator-> |
| getMapInfo(rightMost->getValueId())->getAttr(); |
| |
| // Add the REAL Boolean AND Clause. The AND between the WHEN |
| // and the TRUE (of the THEN) |
| // |
| |
| allAttr[0]->resetShowplan(); |
| |
| ex_bool_clause * andClause = |
| new(space) ex_bool_clause(ITM_AND, allAttr, space); |
| |
| generator->getExpGenerator()->linkClause(this, andClause); |
| |
| andBranchClause->set_branch_clause((ex_clause *)andClause); |
| |
| // Remove Short Circuit Map Table. The code generated for the |
| // THEN clause should not be available for processing the WHEN |
| // clauses. |
| mt = generator->unlinkLast(); |
| GenAssert(mt == thenscMapTable, "Unexpected map table"); |
| |
| // Clear the codegen flag in the Short Circuit MapTable. The |
| // items codegened for one THEN clause should not be available |
| // for the next THEN clause. |
| // |
| thenscMapTable->resetCodeGen(); |
| |
| // Create the real Boolean OR Clause between this AND and the |
| // previous AND or previous OR of ANDS. The first time thru the |
| // loop there is no previous so only do this after the first |
| // iteration. |
| if(i > 0) { |
| // Add OR |
| |
| prevAttr[2] = mapInfoAndNode->getAttr(); |
| |
| prevAttr[0]->resetShowplan(); |
| |
| ex_bool_clause * orClause = |
| new(space) ex_bool_clause(ITM_OR, prevAttr, space); |
| |
| generator->getExpGenerator()->linkClause(this, orClause); |
| |
| orBranchClause->set_branch_clause((ex_clause *)orClause); |
| |
| } |
| |
| // If there is another CLAUSE to process after this one (either |
| // another WHEN/THEN pair or an ELSE clause), add the OR Branch |
| // clause to branch around WHEN/THENs (ELSE) once one of the THENs has |
| // been taken. |
| // |
| if(i < (thens.entries() - 1)) { |
| |
| // Add OR Branch Create a dummy OR node and bind it. Just |
| // used to get a ValueId. Will not call codegen in this OR |
| // node. (note that the OR is not between the right values. |
| // It is okay since it is just used as a placeholder.) |
| // |
| ItemExpr *orNode = new(generator->wHeap()) BiLogic(ITM_OR, andNode, |
| andNode); |
| orNode->bindNode(generator->getBindWA()); |
| |
| // Create temp space for the result of the OR clause. |
| MapInfo *mapInfoOrNode = |
| generator->getExpGenerator()->addTemporary(orNode->getValueId(), NULL); |
| |
| // On the first time, the OR is between two ANDs, after that it is between |
| // the previous OR (OR of ANDS) and the current AND. |
| // |
| if(i > 0) { |
| prevAttr[1] = prevAttr[0]; |
| } else { |
| prevAttr[1] = mapInfoAndNode->getAttr(); |
| } |
| prevAttr[0] = mapInfoOrNode->getAttr(); |
| |
| branch_attr[0] = prevAttr[0]->newCopy(generator->wHeap()); |
| branch_attr[0]->copyLocationAttrs(prevAttr[0]); |
| |
| branch_attr[1] = prevAttr[1]->newCopy(generator->wHeap()); |
| branch_attr[1]->copyLocationAttrs(prevAttr[1]); |
| |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| |
| branch_attr[0]->resetShowplan(); |
| orBranchClause = new(space) ex_branch_clause(ITM_OR, branch_attr, space); |
| |
| generator->getExpGenerator()->linkClause(0, orBranchClause); |
| } |
| } |
| |
| // If there is an ELSE clause, generate code for the ELSE clause |
| // and OR it into the rest. |
| if(thens.entries() > whens.entries()) { |
| ItemExpr *else_part = thens[whens.entries()].getItemExpr(); |
| |
| // Use the Short Circuit Map Table for the ELSE clause. |
| // |
| generator->appendAtEnd(thenscMapTable); |
| else_part->preCodeGen(generator); |
| |
| generator->getExpGenerator()->incrementLevel(); |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| else_part->codeGen(generator); |
| generator->getExpGenerator()->decrementLevel(); |
| |
| prevAttr[2] = generator->getAttr(else_part); |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| |
| prevAttr[0]->resetShowplan(); |
| |
| ex_bool_clause * orClause = |
| new(space) ex_bool_clause(ITM_OR, prevAttr, space); |
| |
| generator->getExpGenerator()->linkClause(this, orClause); |
| |
| orBranchClause->set_branch_clause((ex_clause *)orClause); |
| |
| mt = generator->unlinkLast(); |
| GenAssert(mt == thenscMapTable, "Unexpected map table"); |
| |
| thenscMapTable->resetCodeGen(); |
| } |
| generator->getExpGenerator()->setClauseLinked(FALSE); |
| |
| // delete thenscMapTable; |
| generator->appendAtEnd(thenscMapTable); |
| generator->removeLast(); |
| |
| mt = generator->getLastMapTable(); |
| GenAssert(mt == whenscMapTable, "Unexpected map table"); |
| generator->removeLast(); |
| |
| generator->getExpGenerator()->decrementLevel(); |
| |
| return 0; |
| |
| } |
| |
| char * str = new(generator->wHeap()) char[100]; |
| |
| ItemExpr *ifThenElse = child(0); |
| for (; |
| (ifThenElse != NULL) AND |
| (ifThenElse->getOperatorType() == ITM_IF_THEN_ELSE); |
| ifThenElse = ifThenElse->child(2)) |
| { |
| ItemExpr * when_part = ifThenElse->child(0); |
| ItemExpr * then_part = new(generator->wHeap()) Cast(ifThenElse->child(1), |
| &(getValueId().getType())); |
| |
| then_part->bindNode(generator->getBindWA()); |
| |
| // set the buffer location of all the convert nodes that were added |
| // in the last step to be the same as that of the case node. This |
| // will make all result values to be moved to the same location. |
| MapInfo * map_info |
| = generator->addMapInfo(then_part->getValueId(), |
| case_map_info_attr); |
| (map_info->getAttr())->copyLocationAttrs(case_map_info_attr); |
| |
| ItemExpr *caseOperand = removeCaseOperand(); |
| if (caseOperand != NULL) |
| strcpy(str, "@A1 = @A2 AND @B3"); |
| else |
| strcpy(str, "@B2 AND @B3"); |
| |
| ItemExpr * andNode |
| = generator->getExpGenerator()->createExprTree(str, 0, 3, |
| caseOperand, |
| when_part, |
| new(generator->wHeap()) |
| BoolVal(ITM_RETURN_TRUE, then_part)); |
| |
| if (rootNode) |
| { |
| rootNode = generator->getExpGenerator()->createExprTree("@B1 OR @B2", 0, 2, |
| rootNode, andNode); |
| } |
| else |
| { |
| rootNode = andNode; |
| } |
| } // for |
| |
| // now add the else part, if present |
| if (ifThenElse) |
| { |
| ItemExpr * conv_node = new(generator->wHeap()) Cast(ifThenElse, |
| &(getValueId().getType())); |
| |
| conv_node->bindNode(generator->getBindWA()); |
| MapInfo * map_info = |
| generator->addMapInfo(conv_node->getValueId(), |
| case_map_info_attr); |
| |
| (map_info->getAttr())->copyLocationAttrs(case_map_info_attr); |
| |
| rootNode = new(generator->wHeap()) BiLogic(ITM_OR, rootNode, |
| new(generator->wHeap()) BoolVal(ITM_RETURN_TRUE, |
| conv_node)); |
| } |
| |
| NADELETEBASIC( str, generator->wHeap()) ; |
| |
| GenAssert(rootNode,"Case::codeGen: Expected ELSE condition"); // ported back from R2 |
| |
| #ifdef _DEBUG |
| if (getenv("GEN_FUNC_DEBUG")) |
| { |
| NAString unparsed; |
| unparse(unparsed); |
| cout << "(a)" << unparsed << endl; |
| |
| unparsed = ""; |
| rootNode->unparse(unparsed); |
| cout << "(b)" << unparsed << endl; |
| } |
| #endif |
| |
| rootNode->bindNode(generator->getBindWA()); |
| |
| GenAssert(rootNode,"Case::codeGen: Expected ELSE condition"); |
| // generate child |
| rootNode->preCodeGen(generator); |
| rootNode->codeGen(generator); |
| |
| return 0; |
| } |
| |
| short Cast::codeGen(Generator * generator) |
| { |
| |
| Attributes ** attr; |
| |
| ExpGenerator * eg = generator->getExpGenerator(); |
| |
| if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1) |
| return 0; |
| |
| // if temp space is needed for this operation, set it. |
| if (attr[0]->isComplexType()) |
| { |
| eg->addTempsLength(((ComplexType *)attr[0])->setTempSpaceInfo(getOperatorType(), |
| eg->getTempsLength())); |
| } |
| ex_conv_clause * conv_clause; |
| if(attr[0]->getNullFlag()) //if target is nullable |
| conv_clause = new(generator->getSpace()) ex_conv_clause(getOperatorType(), attr, |
| generator->getSpace(), |
| 1 + getArity(), |
| checkTruncationError(), |
| reverseDataErrorConversionFlag_, |
| noStringTruncationWarnings(), |
| convertNullWhenError()); |
| else |
| conv_clause = new(generator->getSpace()) ex_conv_clause(getOperatorType(), attr, |
| generator->getSpace(), |
| 1 + getArity(), |
| checkTruncationError(), |
| reverseDataErrorConversionFlag_, |
| noStringTruncationWarnings(), |
| FALSE); |
| |
| conv_clause->setTreatAllSpacesAsZero(treatAllSpacesAsZero()); |
| |
| if ( CmpCommon::getDefault(MARIAQUEST_PROCESS) == DF_ON ) |
| { |
| conv_clause->setAllowSignInInterval(TRUE); |
| conv_clause->setNoDatetimeValidation(TRUE); |
| } |
| |
| conv_clause->setAllowSignInInterval(allowSignInInterval()); |
| conv_clause->setSrcIsVarcharPtr(srcIsVarcharPtr()); |
| |
| generator->getExpGenerator()->linkClause(this, conv_clause); |
| |
| return 0; |
| } |
| |
| short CastType::codeGen(Generator * generator) |
| { |
| if (makeNullable_) |
| return Cast::codeGen(generator); |
| |
| Attributes ** attr; |
| |
| ExpGenerator * eg = generator->getExpGenerator(); |
| |
| if (eg->genItemExpr(this, &attr, (1+getArity()), -1) == 1) |
| return 0; |
| |
| ExFunctionCastType * ct = |
| new(generator->getSpace()) ExFunctionCastType(getOperatorType(), attr, |
| generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, ct); |
| |
| return 0; |
| } |
| |
| short CompEncode::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| |
| CharInfo::Collation collation = encodedCollation_; |
| |
| ex_function_encode * function_clause = |
| new(generator->getSpace()) ex_function_encode(getOperatorType(), |
| attr, generator->getSpace(), |
| collation, |
| descFlag_, |
| collationType_ |
| ); |
| |
| // don't need data alignment for the operand since it is treated |
| // as a byte stream to encode the value. |
| function_clause->getOperand(1)->dontNeedDataAlignment(); |
| |
| // encode as case insensitive if needed. |
| if (caseinsensitiveEncode_) |
| { |
| function_clause->setCaseInsensitive(TRUE); |
| } |
| |
| if (regularNullability_) |
| { |
| function_clause->setRegularNullability(TRUE); |
| } |
| |
| if (isDecode()) |
| function_clause->setIsDecode(TRUE); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| if (CollationInfo::isSystemCollation(collation)) |
| //test implies child is of character type and has a system collation |
| { |
| short nPasses = CollationInfo::getCollationNPasses(collation); |
| |
| GenAssert(function_clause->getOperand(1)->getLength() * nPasses |
| <= function_clause->getOperand(0)->getLength(), |
| "Not enough storage allocated for encode"); |
| } |
| else |
| { |
| // Runtime assumes that the target is large enough to hold the source. |
| // |
| if (NOT regularNullability_) |
| { |
| GenAssert(function_clause->getOperand(1)->getLength() + |
| function_clause->getOperand(1)->getNullIndicatorLength() |
| <= function_clause->getOperand(0)->getLength(), |
| "Not enough storage allocated for encode"); |
| } |
| } |
| |
| return 0; |
| } |
| |
| short CompDecode::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| CharInfo::Collation collation = encodedCollation_; |
| |
| ex_function_encode * function_clause = |
| new(generator->getSpace()) ex_function_encode(getOperatorType(), |
| attr, generator->getSpace(), |
| collation, |
| descFlag_, |
| collationType_ |
| ); |
| |
| // don't need data alignment for the operand since it is treated |
| // as a byte stream to encode the value. |
| function_clause->getOperand(1)->dontNeedDataAlignment(); |
| |
| // encode as case insensitive if needed. |
| if (caseinsensitiveEncode_) |
| { |
| function_clause->setCaseInsensitive(TRUE); |
| } |
| |
| if (regularNullability_) |
| { |
| function_clause->setRegularNullability(TRUE); |
| } |
| |
| function_clause->setIsDecode(TRUE); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| if (0) //CollationInfo::isSystemCollation(collation)) |
| //test implies child is of character type and has a system collation |
| { |
| short nPasses = CollationInfo::getCollationNPasses(collation); |
| |
| GenAssert(function_clause->getOperand(1)->getLength() * nPasses |
| <= function_clause->getOperand(0)->getLength(), |
| "Not enough storage allocated for decode"); |
| } |
| else if (0) |
| { |
| // Runtime assumes that the target is large enough to hold the source. |
| // |
| if (NOT regularNullability_) |
| { |
| GenAssert(function_clause->getOperand(1)->getStorageLength() |
| <= function_clause->getOperand(0)->getLength(), |
| "Not enough storage allocated for decode"); |
| } |
| } |
| |
| return 0; |
| } |
| |
| short ExplodeVarchar::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * explode_clause = |
| new(generator->getSpace()) ex_function_explode_varchar(getOperatorType(), |
| 2, |
| attr, generator->getSpace(), |
| forInsert_); |
| |
| generator->getExpGenerator()->linkClause(this, explode_clause); |
| |
| return 0; |
| } |
| |
| short Hash::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_hash(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| // don't need data alignment for the operand since it is treated |
| // as a byte stream to hash the value. |
| function_clause->getOperand(1)->dontNeedDataAlignment(); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short HashComb::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExHashComb(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short HiveHashComb::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExHiveHashComb(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| |
| // -------------------------------------------------------------- |
| // member functions for HashDistPartHash operator |
| // Hash Function used by Hash Partitioning. This function cannot change |
| // once Hash Partitioning is released! Defined for all data types, |
| // returns a 32 bit non-nullable hash value for the data item. |
| //-------------------------------------------------------------- |
| short HashDistPartHash::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * hashClause = |
| new(generator->getSpace()) ExHDPHash(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| // don't need data alignment for the operand since it is treated |
| // as a byte stream to hash the value. |
| hashClause->getOperand(1)->dontNeedDataAlignment(); |
| |
| generator->getExpGenerator()->linkClause(this, hashClause); |
| |
| return 0; |
| } |
| |
| // -------------------------------------------------------------- |
| // member functions for HashDistPartHashComp operator |
| // This function is used to combine two hash values to produce a new |
| // hash value. Used by Hash Partitioning. This function cannot change |
| // once Hash Partitioning is released! Defined for all data types, |
| // returns a 32 bit non-nullable hash value for the data item. |
| // -------------------------------------------------------------- |
| // |
| short HashDistPartHashComb::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * hashCombClause = |
| new(generator->getSpace()) ExHDPHashComb(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, hashCombClause); |
| |
| return 0; |
| } |
| |
| short HiveHash::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_hivehash(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| // don't need data alignment for the operand since it is treated |
| // as a byte stream to hive hash the value. |
| function_clause->getOperand(1)->dontNeedDataAlignment(); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short PivotGroup::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_pivot_group_clause(getOperatorType(), |
| (short) (1+getArity()), |
| attr, |
| (char*)delim_.data(), |
| maxLen_, |
| orderBy_, |
| generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short ReplaceNull::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) |
| ex_function_replace_null(getOperatorType(), attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| return 0; |
| } |
| |
| short MathFunc::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| |
| ex_clause * function_clause = NULL; |
| function_clause = |
| new(generator->getSpace()) ExFunctionMath(getOperatorType(), |
| (1+getArity()), |
| attr, generator->getSpace()); |
| |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short Modulus::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_mod(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| |
| short Narrow::codeGen(Generator * generator) |
| { |
| return Cast::codeGen(generator); |
| } |
| |
| |
| short Mask::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_mask(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short Shift::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExFunctionShift(getOperatorType(), |
| attr, generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short NoOp::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_noop_clause(); |
| |
| // this is the last clause. |
| function_clause->setLastClause(); |
| generator->getExpGenerator()->linkClause(0, function_clause); |
| |
| return 0; |
| } |
| |
| short Translate::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| NABoolean unicodeToUnicode = FALSE; |
| Int16 translateFlags = 0; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| Int32 convType = CONV_UNKNOWN; |
| switch ( map_table_id_ ) { |
| case ISO88591_TO_UNICODE: |
| convType = CONV_ASCII_UNICODE_V; |
| break; |
| case SJIS_TO_UNICODE: |
| convType = CONV_SJIS_F_UNICODE_V; |
| break; |
| case UNICODE_TO_SJIS: |
| convType = CONV_UNICODE_F_SJIS_V; |
| break; |
| case SJIS_TO_UCS2: |
| convType = CONV_SJIS_F_UCS2_V; |
| break; |
| case UTF8_TO_UCS2: |
| convType = CONV_UTF8_F_UCS2_V; |
| unicodeToUnicode = TRUE; |
| break; |
| case UCS2_TO_SJIS: |
| convType = CONV_UCS2_F_SJIS_V; |
| break; |
| case UCS2_TO_UTF8: |
| convType = CONV_UCS2_F_UTF8_V; |
| unicodeToUnicode = TRUE; |
| break; |
| case GBK_TO_UTF8: |
| convType = CONV_GBK_F_UTF8_V; |
| break; |
| case UNICODE_TO_ISO88591: |
| convType = CONV_UNICODE_F_ASCII_V; |
| break; |
| case KANJI_MP_TO_ISO88591: |
| case KSC5601_MP_TO_ISO88591: |
| convType = CONV_ASCII_F_V; |
| break; |
| } |
| |
| if (CmpCommon::getDefault(TRANSLATE_ERROR) == DF_OFF || |
| (unicodeToUnicode && |
| CmpCommon::getDefault(TRANSLATE_ERROR_UNICODE_TO_UNICODE) == DF_OFF)) |
| translateFlags |= ex_function_translate::TRANSLATE_FLAG_ALLOW_INVALID_CODEPOINT; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_translate( |
| getOperatorType(), |
| attr, |
| generator->getSpace(), |
| convType, |
| translateFlags |
| ); |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short Trim::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = 0; |
| |
| const CharType& trimSourceType = |
| (CharType&)((child(0)->getValueId()).getType()); |
| |
| const CharType& trimCharT = |
| (CharType&)((child(1)->getValueId()).getType()); |
| |
| switch ( trimSourceType.getCharSet() ) |
| { |
| case CharInfo::ISO88591: |
| case CharInfo::UTF8: |
| // case CharInfo::SJIS: // Uncomment this if we ever support SJIS |
| function_clause = new(generator->getSpace()) |
| ex_function_trim_char(ITM_TRIM, |
| attr, |
| generator->getSpace(), getTrimMode() |
| ); |
| ((ex_function_trim_char *)function_clause)->setCollation(getCollation()); |
| |
| if (CollationInfo::isSystemCollation(getCollation())) |
| { |
| Lng32 len = 0; |
| const CharType * ctyp ; |
| |
| const NAType & typ1 = child(1)->getValueId().getType(); |
| ctyp = (CharType *)&typ1; |
| |
| len = CompEncode::getEncodedLength(getCollation(), |
| CollationInfo::Search, |
| ctyp->getNominalSize(), |
| ctyp->supportsSQLnull()); |
| |
| ((ex_function_trim_char*)function_clause)->setSrcStrEncodedLength((Int16)len); |
| |
| const NAType & typ0= child(0)->getValueId().getType(); |
| ctyp = (CharType *)&typ0; |
| |
| len = CompEncode::getEncodedLength(getCollation(), |
| CollationInfo::Search, |
| ctyp->getNominalSize(), |
| ctyp->supportsSQLnull()); |
| |
| ((ex_function_trim_char*)function_clause)->setTrimCharEncodedLength((Int16)len); |
| } |
| |
| // pcode is only supported if the trim char is a single byte literal with |
| // length of 1 and value of ' ' |
| if (NOT ((child(0)->castToItemExpr()->getOperatorType() == ITM_CONSTANT) && |
| (trimSourceType.getFSDatatype() == REC_BYTE_F_ASCII) && |
| (trimSourceType.getNominalSize() == 1) && |
| (str_cmp((char*)((ConstValue*)(child(0)->castToItemExpr()))->getConstValue(), " ", 1) == 0))) |
| { |
| function_clause->setNoPCodeAvailable(TRUE); |
| } |
| break; |
| |
| case CharInfo::UCS2: |
| function_clause = new(generator->getSpace()) |
| ex_function_trim_doublebyte(ITM_TRIM_DOUBLEBYTE, |
| attr, |
| generator->getSpace(), getTrimMode() |
| ); |
| break; |
| |
| default: |
| GenAssert(0, "unknown value for bytes-per-char."); |
| } |
| |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short DateFormat::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, |
| &attr, |
| 1 + getArity(), |
| -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_dateformat(getOperatorType(), |
| attr, |
| generator->getSpace(), |
| getExpDatetimeFormat()); |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short Extract::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| if (generator->getExpGenerator()->genItemExpr(this, |
| &attr, |
| 1 + getArity(), |
| -1) == 1) |
| return 0; |
| |
| ex_clause * function_clause = |
| new(generator->getSpace()) ex_function_extract(getOperatorType(), |
| attr, |
| generator->getSpace(), |
| getExtractField()); |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short RangeLookup::codeGen(Generator * generator) |
| { |
| Attributes ** attr2; |
| Attributes ** attr3; |
| Lng32 arity = getArity(); |
| Lng32 keysLen = splitKeysLen(); |
| Attributes *splitKeyAttr; |
| char *constKeyArray; |
| ConstValue *constValSplitKeys; |
| |
| // generate code for child (allocates an array with 2 Attributes pointers) |
| if (generator->getExpGenerator()->genItemExpr(this, |
| &attr2, |
| 1 + arity, |
| -1) == 1) |
| return 0; |
| |
| // now allocate a third child for this clause, which is a constant |
| // array of all the encoded start key values |
| Int32 numAttrs = arity+2; |
| Int32 numAttrsShowPlan = (generator->getExpGenerator()->getShowplan() ? numAttrs : 0); |
| |
| attr3 = new(generator->wHeap()) Attributes * [numAttrs + numAttrsShowPlan]; |
| |
| // copy 2 Attribute pointers and 2 showplan attribute pointers to array with 3 pointers |
| str_cpy_all((char *) attr3, |
| (const char *) attr2, |
| sizeof(Attributes *) * (numAttrs-1)); |
| if (numAttrsShowPlan) |
| { |
| str_cpy_all((char *) &attr3[numAttrs], |
| (const char *) &attr2[numAttrs-1], |
| sizeof(Attributes *) * (numAttrs-1)); |
| } |
| |
| // make a ConstValue that is a huge character column with all the |
| // split keys in it, then generate code for it and get its Attributes |
| |
| constKeyArray = new(generator->wHeap()) char [keysLen]; |
| // now fill the allocated constant space with the data |
| copySplitKeys(constKeyArray, keysLen); |
| |
| constValSplitKeys = new (generator->wHeap()) ConstValue( |
| new (generator->wHeap()) SQLChar(generator->wHeap(), keysLen,FALSE), |
| constKeyArray, |
| keysLen, |
| NULL, |
| generator->wHeap()); |
| constValSplitKeys->bindNode(generator->getBindWA()); |
| constValSplitKeys->codeGen(generator); |
| |
| // code generation is done, now get the Attributes info back |
| MapInfo * map_info = generator->getMapInfoAsIs( |
| constValSplitKeys->getValueId()); |
| GenAssert(map_info, "failed to generate long constant for split keys"); |
| splitKeyAttr = map_info->getAttr(); |
| |
| // copy last Attributes pointer |
| attr3[numAttrs-1] = splitKeyAttr; |
| |
| // ...and showplan equivalent, if needed |
| if (numAttrsShowPlan) |
| { |
| attr3[numAttrs + numAttrsShowPlan - 1] = new (generator->wHeap()) |
| ShowplanAttributes( |
| constValSplitKeys->getValueId(), |
| convertNAString("SplitKeysForRangeRepartitioning", |
| generator->wHeap())); |
| } |
| |
| // now that we prepared all the inputs, add the clause itself |
| ex_clause * function_clause = |
| new(generator->getSpace()) ExFunctionRangeLookup( |
| attr3, |
| generator->getSpace(), |
| getNumOfPartitions(), |
| getEncodedBoundaryKeyLength()); |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short UDFunction::codeGen(Generator * /* generator */) |
| { |
| GenAssert(0, "UDFunction::codeGen. We don't have any!"); |
| |
| return -1; |
| } |
| |
| short |
| ScalarVariance::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause *function_clause = 0; |
| |
| switch(getOperatorType()) |
| { |
| case ITM_VARIANCE: |
| function_clause = new(space) ExFunctionSVariance(attr, space); |
| break; |
| case ITM_STDDEV: |
| function_clause = new(space) ExFunctionSStddev(attr, space); |
| break; |
| default: |
| GenAssert(0,"ScalarVariance: Unknown operator"); |
| break; |
| } |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| // UnPackCol::codeGen() ---------------------------- |
| // UnPackCol is implemented by the ExUnPackCol function_clause. |
| // |
| short |
| UnPackCol::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause *function_clause = NULL; |
| |
| switch (child(0)->getValueId().getType().getTypeQualifier()) { |
| case NA_CHARACTER_TYPE: |
| // A packed column.... |
| // |
| function_clause = new(space) ExUnPackCol(attr, |
| space, |
| width_, |
| base_, |
| nullsPresent_); |
| break; |
| case NA_NUMERIC_TYPE: |
| // A virtually packed SYSKEY column... |
| // |
| function_clause = new(space) ex_arith_clause(ITM_PLUS, attr, space, |
| 0, FALSE); |
| break; |
| default: |
| GenAssert(0, "UnPackCol::codeGen() Unknown type"); |
| break; |
| } |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| // RowsetArrayScan::codeGen() ---------------------------- |
| // RowsetArrayScan is implemented by the ExRowsetArrayScan function_clause. |
| // |
| short |
| RowsetArrayScan::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| ex_clause * function_clause = 0; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, |
| (1 + getArity()), -1) == 1) |
| return 0; |
| |
| switch (getOperatorType()) { |
| case ITM_ROWSETARRAY_SCAN: |
| function_clause = new(space) ExRowsetArrayScan(attr, |
| space, |
| maxNumElem_, |
| elemSize_, |
| elemNullInd_); |
| break; |
| |
| case ITM_ROWSETARRAY_ROWID: |
| function_clause = new(space) ExRowsetArrayRowid(attr, |
| space, |
| maxNumElem_); |
| break; |
| |
| default: |
| GenAssert(0,"ScalarVariance: Unknown operator"); |
| break; |
| } |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short |
| RowsetArrayInto::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| ex_clause * function_clause = 0; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, |
| (1 + getArity()), -1) == 1) |
| return 0; |
| |
| function_clause = new(space) ExRowsetArrayInto(attr, |
| space, |
| maxNumElem_, |
| elemSize_, |
| elemNullInd_); |
| |
| if(function_clause) |
| generator->getExpGenerator()->linkClause(this,function_clause); |
| |
| return 0; |
| } |
| |
| short RandomNum::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| /* |
| // convert seed, if present, to 'unsigned int'. |
| if (getArity() == 1) |
| { |
| ItemExpr * newChild = |
| new (generator->wHeap()) |
| Cast(child(0), |
| new (generator->wHeap()) SQLInt(generator->wHeap(), FALSE, FALSE)); |
| newChild = newChild->bindNode(generator->getBindWA()); |
| newChild->preCodeGen(generator); |
| |
| setChild(0, newChild); |
| } |
| */ |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| ex_clause *function_clause = new (space) ExFunctionRandomNum(ITM_RANDOMNUM, |
| (1+getArity()), |
| simpleRandom_, |
| attr, |
| space); |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short HashDistrib::codeGen(Generator *generator) |
| { |
| GenAssert(0, "HashDistrib::codeGen. Should use ProgDistrib or Hash2Distrib"); |
| return -1; |
| } |
| |
| short Hash2Distrib::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause *function_clause = new (space) ExHash2Distrib(attr, space); |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short ProgDistrib::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause *function_clause = new (space) ExProgDistrib(attr, space);; |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short ProgDistribKey::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause *function_clause = new (space) ExProgDistribKey(attr, space); |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| short PAGroup::codeGen(Generator *generator) |
| { |
| Attributes **attr; |
| Space *space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()-> |
| genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ex_clause *function_clause = new (space) ExPAGroup(attr, space); |
| |
| if (function_clause) |
| generator->getExpGenerator()->linkClause(this, function_clause); |
| |
| return 0; |
| } |
| |
| #include "NumericType.h" |
| |
| short PackFunc::codeGen(Generator* generator) |
| { |
| Attributes** attr; |
| Space* space = generator->getSpace(); |
| |
| if(generator->getExpGenerator()->genItemExpr(this,&attr,(1 + getArity()),-1) == 1) |
| return 0; |
| |
| // If format info is not valid, synthesize them from child's format info. |
| if(!isFormatInfoValid_) |
| { |
| const NAType* columnType = &child(0)->getValueId().getType(); |
| deriveFormatInfoFromUnpackType(columnType); |
| } |
| |
| ex_clause* function_clause = new(space) ExFunctionPack(attr, |
| space, |
| width_, |
| base_, |
| nullsPresent_); |
| if(function_clause) |
| generator->getExpGenerator()->linkClause(this,function_clause); |
| |
| return 0; |
| } |
| |
| // |
| // From MAX (child(0), child(1)), |
| // Generates a CASE expression of the form CASE WHEN child(0) > child(1) THEN child(0) ELSE child(1). |
| // |
| |
| short ItmScalarMinMax::codeGen(Generator* generator) |
| { |
| const char *str = NULL; |
| |
| switch (getOperatorType()) { |
| |
| case ITM_SCALAR_MAX: // SCALAR_MAX(5, 6) ==> 6; SCALAR_MAX(5, NULL) ==> 5; SCALAR_MAX(NULL, 6) ==> 6 |
| str = "CASE WHEN @A1 IS NULL OR @A2 > @A1 THEN @A2 ELSE @A1 END"; |
| break; |
| |
| case ITM_SCALAR_MIN: // SCALAR_MIN(5, 6) ==> 5; SCALAR_MIN (5, NULL) ==> 5; SCALAR_MIN (NULL, 6) ==> 6 |
| str = "CASE WHEN @A1 IS NULL OR @A2 < @A1 THEN @A2 ELSE @A1 END"; |
| break; |
| |
| default: |
| break; |
| |
| } //switch on getOperatorType() |
| |
| ItemExpr *newExpr = generator->getExpGenerator()->createExprTree(str, 0, 2, child(0), child(1)); |
| newExpr = new (generator->wHeap()) Cast (newExpr, getValueId().getType().newCopy(generator->wHeap())); |
| |
| getValueId().replaceItemExpr(newExpr); // I am now an ITM_CASE |
| newExpr->synthTypeAndValueId(TRUE); |
| setReplacementExpr(newExpr); |
| |
| newExpr->preCodeGen(generator); |
| newExpr->codeGen(generator); |
| |
| return 0; |
| } |
| |
| short HbaseColumnLookup::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| std::string colFam; |
| std::string colName; |
| ExFunctionHbaseColumnLookup::extractColFamilyAndName( |
| hbaseCol_.data(), -1, FALSE, colFam, colName); |
| |
| if (colFam.empty()) |
| { |
| GenAssert(0, "Must specify the column family in the COLUMN_LOOKUP function"); |
| } |
| |
| NAString qualColName = colFam.data(); |
| qualColName += ":"; |
| qualColName += colName.data(); |
| |
| ExFunctionHbaseColumnLookup * cl = |
| new(generator->getSpace()) ExFunctionHbaseColumnLookup |
| (getOperatorType(), |
| attr, |
| qualColName.data(), |
| space); |
| |
| if (cl) |
| generator->getExpGenerator()->linkClause(this, cl); |
| |
| return 0; |
| } |
| |
| short HbaseColumnsDisplay::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| char * colNames = NULL; |
| NAString allCols; |
| if ((csl()) && (csl()->entries() > 0)) |
| { |
| for (Lng32 i = 0; i < csl()->entries(); i++) |
| { |
| NAString * nas = (NAString*)(*csl())[i]; |
| |
| short colNameLen = nas->length(); |
| allCols.append((char*)&colNameLen, sizeof(colNameLen)); |
| |
| allCols += *nas; |
| } |
| |
| colNames = |
| generator->getSpace()->allocateAndCopyToAlignedSpace(allCols.data(), allCols.length()); |
| |
| } |
| |
| ExFunctionHbaseColumnsDisplay * cd = |
| new(generator->getSpace()) ExFunctionHbaseColumnsDisplay |
| (getOperatorType(), |
| attr, |
| (csl() ? csl()->entries() : 0), |
| colNames, |
| space); |
| |
| if (cd) |
| generator->getExpGenerator()->linkClause(this, cd); |
| |
| generator->getExpGenerator()->setPCodeMode( ex_expr::PCODE_NONE ); |
| |
| return 0; |
| } |
| |
| short HbaseColumnCreate::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, 1, -1) == 1) |
| return 0; |
| |
| short numEntries = hccol_->entries(); |
| |
| Lng32 colValuesLen = 0; |
| NAString colNames; |
| NAString colValues; |
| |
| ValueIdList colCreateVIDlist; |
| |
| for (Lng32 i = 0; i < numEntries; i++) |
| { |
| HbaseColumnCreateOptions * hcco = (*hccol_)[i]; |
| |
| hcco->colName()->preCodeGen(generator); |
| hcco->colVal()->preCodeGen(generator); |
| |
| const NAType &childType = hcco->colVal()->getValueId().getType(); |
| |
| if (NOT childType.supportsSQLnull()) |
| { |
| NAType *newType= childType.newCopy(generator->wHeap()); |
| newType->setNullable(TRUE); |
| ItemExpr * ne = new (generator->wHeap()) Cast(hcco->colVal(), |
| newType); |
| ne = ne->bindNode(generator->getBindWA()); |
| ne->preCodeGen(generator); |
| hcco->setColVal(ne); |
| } |
| |
| colCreateVIDlist.insert(hcco->colName()->getValueId()); |
| colCreateVIDlist.insert(hcco->colVal()->getValueId()); |
| } |
| |
| ULng32 tupleLength = 0; |
| short colValVCIndLen = 0; |
| generator->getExpGenerator()->processValIdList(colCreateVIDlist, |
| ExpTupleDesc::SQLARK_EXPLODED_FORMAT, |
| tupleLength, |
| attr[0]->getAtp(), |
| attr[0]->getAtpIndex(), |
| NULL, |
| ExpTupleDesc::SHORT_FORMAT, |
| attr[0]->getOffset() + |
| (sizeof(numEntries) + sizeof(colNameMaxLen_) + |
| sizeof(colValVCIndLen) + sizeof(colValMaxLen_))); |
| |
| for (Lng32 i = 0; i < numEntries; i++) |
| { |
| HbaseColumnCreateOptions * hcco = (*hccol_)[i]; |
| |
| hcco->colName()->codeGen(generator); |
| hcco->colVal()->codeGen(generator); |
| |
| const NAType &childType = hcco->colVal()->getValueId().getType(); |
| colValVCIndLen = (childType.isVaryingLen() ? |
| childType.getVarLenHdrSize() : 0); |
| } |
| |
| ExFunctionHbaseColumnCreate * cl = |
| new(generator->getSpace()) ExFunctionHbaseColumnCreate |
| (getOperatorType(), |
| attr, |
| numEntries, |
| colNameMaxLen_, |
| colValMaxLen_, |
| colValVCIndLen, |
| generator->getSpace()); |
| |
| generator->getExpGenerator()->linkClause(this, cl); |
| |
| return 0; |
| } |
| |
| |
| short LOBinsert::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| char * loc = NULL; |
| if (NOT lobStorageLocation().isNull()) |
| { |
| // loc = space->AllocateAndCopyToAlignedSpace(lobStorageLocation(), 0); |
| } |
| |
| ExpLOBinsert * li = |
| new(generator->getSpace()) ExpLOBinsert |
| (getOperatorType(), |
| getArity()+1, |
| attr, |
| objectUID_, |
| (short)insertedTableSchemaName().length(), |
| (char*)insertedTableSchemaName().data(), |
| space); |
| |
| if (obj_ == LOBoper::STRING_) |
| li->setFromString(TRUE); |
| else if (obj_ == LOBoper::FILE_) |
| li->setFromFile(TRUE); |
| else if (obj_ == LOBoper::LOAD_) |
| li->setFromLoad(TRUE); |
| else if (obj_ == LOBoper::LOB_) |
| { |
| if (lobStorageType() != Lob_External_HDFS_File) |
| li->setFromLob(TRUE); |
| else |
| li->setFromLobExternal(TRUE); |
| } |
| else if (obj_ == LOBoper::EXTERNAL_) |
| li->setFromExternal(TRUE); |
| else if (obj_ ==LOBoper::BUFFER_) |
| li->setFromBuffer(TRUE); |
| else if(obj_ == LOBoper::EMPTY_LOB_) |
| li->setFromEmpty(TRUE); |
| |
| if (CmpCommon::getDefault(LOB_LOCKING) == DF_ON) |
| li->setLobLocking(TRUE); |
| else |
| li->setLobLocking(FALSE); |
| |
| li->lobNum() = lobNum(); |
| li->setLobStorageType(lobStorageType()); |
| li->setLobStorageLocation((char*)lobStorageLocation().data()); |
| li->setLobSize(lobSize()); |
| li->setLobMaxSize(getLobMaxSize()); |
| li->setLobMaxChunkMemSize(getLobMaxChunkMemSize()); |
| li->setLobGCLimit(getLobGCLimit()); |
| li->setLobHdfsServer((char *)getLobHdfsServer().data()); |
| li->setLobHdfsPort(getLobHdfsPort()); |
| generator->getExpGenerator()->linkClause(this, li); |
| |
| return 0; |
| } |
| |
| short LOBdelete::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExpLOBdelete * ld = |
| new(generator->getSpace()) ExpLOBdelete(getOperatorType(), |
| attr, |
| space); |
| |
| ld->getOperand(0)->setAtp(ld->getOperand(1)->getAtp()); |
| ld->getOperand(0)->setAtpIndex(ld->getOperand(1)->getAtpIndex()); |
| |
| ld->lobNum() = lobNum(); |
| ld->setLobStorageType(lobStorageType()); |
| ld->setLobStorageLocation((char*)lobStorageLocation().data()); |
| ld->setLobHdfsServer((char *)getLobHdfsServer().data()); |
| ld->setLobHdfsPort(getLobHdfsPort()); |
| generator->getExpGenerator()->linkClause(this, ld); |
| |
| return 0; |
| } |
| |
| short LOBupdate::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExpLOBupdate * lu = |
| new(generator->getSpace()) ExpLOBupdate |
| (getOperatorType(), |
| (1+getArity()), |
| attr, |
| objectUID_, |
| (short)updatedTableSchemaName().length(), |
| (char*)updatedTableSchemaName().data(), |
| space); |
| |
| if (append_) |
| lu->setIsAppend(TRUE); |
| |
| if (obj_ == LOBoper::STRING_) |
| lu->setFromString(TRUE); |
| else if (obj_ == LOBoper::FILE_) |
| lu->setFromFile(TRUE); |
| else if (obj_ == LOBoper::LOB_) |
| lu->setFromLob(TRUE); |
| else if (obj_ == LOBoper::EXTERNAL_) |
| lu->setFromExternal(TRUE); |
| else if (obj_ == LOBoper::BUFFER_) |
| lu->setFromBuffer(TRUE); |
| else if(obj_ == LOBoper::EMPTY_LOB_) |
| lu->setFromEmpty(TRUE); |
| if (CmpCommon::getDefault(LOB_LOCKING) == DF_ON) |
| lu->setLobLocking(TRUE); |
| else |
| lu->setLobLocking(FALSE); |
| lu->lobNum() = lobNum(); |
| lu->setLobStorageType(lobStorageType()); |
| lu->setLobStorageLocation((char*)lobStorageLocation().data()); |
| lu->setLobMaxSize(getLobMaxSize()); |
| lu->setLobMaxChunkMemSize(getLobMaxChunkMemSize()); |
| lu->setLobGCLimit(getLobGCLimit()); |
| lu->setLobHdfsServer((char *)getLobHdfsServer().data()); |
| lu->setLobHdfsPort(getLobHdfsPort()); |
| generator->getExpGenerator()->linkClause(this, lu); |
| |
| return 0; |
| } |
| |
| short LOBselect::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExpLOBselect * ls = |
| new(generator->getSpace()) ExpLOBselect(getOperatorType(), |
| attr, |
| space); |
| ls->lobNum() = lobNum(); |
| ls->setLobStorageType(lobStorageType()); |
| ls->setLobStorageLocation((char*)lobStorageLocation().data()); |
| ls->setLobHdfsServer((char *)getLobHdfsServer().data()); |
| ls->setLobHdfsPort(getLobHdfsPort()); |
| generator->getExpGenerator()->linkClause(this, ls); |
| |
| return 0; |
| } |
| |
| short LOBconvertHandle::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExpLOBconvertHandle * lu = |
| new(generator->getSpace()) ExpLOBconvertHandle(getOperatorType(), |
| attr, |
| space); |
| |
| if (obj_ == STRING_) |
| lu->setToString(TRUE); |
| else if (obj_ == LOB_) |
| lu->setToLob(TRUE); |
| |
| lu->lobNum() = lobNum(); |
| lu->setLobStorageType(lobStorageType()); |
| lu->setLobStorageLocation((char*)lobStorageLocation().data()); |
| lu->setLobHdfsServer((char *)getLobHdfsServer().data()); |
| lu->setLobHdfsPort(getLobHdfsPort()); |
| generator->getExpGenerator()->linkClause(this, lu); |
| |
| return 0; |
| } |
| |
| short LOBconvert::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExpLOBconvert * lc = |
| new(generator->getSpace()) ExpLOBconvert(getOperatorType(), |
| attr, |
| space); |
| |
| if (obj_ == STRING_) |
| lc->setToString(TRUE); |
| else if (obj_ == LOB_) |
| lc->setToLob(TRUE); |
| |
| lc->lobNum() = lobNum(); |
| lc->setLobStorageType(lobStorageType()); |
| lc->setLobStorageLocation((char*)lobStorageLocation().data()); |
| generator->getExpGenerator()->linkClause(this, lc); |
| lc->setConvertSize(getTgtSize()); |
| lc->setLobHdfsServer((char *)getLobHdfsServer().data()); |
| lc->setLobHdfsPort(getLobHdfsPort()); |
| return 0; |
| } |
| |
| |
| short SequenceValue::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| Space * space = generator->getSpace(); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| Int64 origCacheSize = naTable_->getSGAttributes()->getSGCache(); |
| Lng32 cacheSize = CmpCommon::getDefaultNumeric(TRAF_SEQUENCE_CACHE_SIZE); |
| if (cacheSize > 0) |
| { |
| ((SequenceGeneratorAttributes*)naTable_->getSGAttributes())->setSGCache(cacheSize); |
| } |
| |
| ExFunctionSequenceValue * sv = |
| new(generator->getSpace()) ExFunctionSequenceValue |
| (getOperatorType(), |
| attr, |
| *naTable_->getSGAttributes(), |
| space); |
| |
| if (cacheSize > 0) |
| ((SequenceGeneratorAttributes*)naTable_->getSGAttributes())->setSGCache(origCacheSize); |
| |
| if (sv) |
| generator->getExpGenerator()->linkClause(this, sv); |
| |
| if (currVal_) |
| sv->setIsCurr(TRUE); |
| |
| return 0; |
| } |
| |
| short HbaseTimestamp::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| MapInfo * hbtMapInfo = generator->getMapInfoAsIs(getValueId()); |
| if (hbtMapInfo && hbtMapInfo->isCodeGenerated()) |
| return 0; |
| |
| Space * space = generator->getSpace(); |
| |
| setChild(0, tsVals_); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExFunctionHbaseTimestamp * hbt = |
| new(generator->getSpace()) ExFunctionHbaseTimestamp |
| (getOperatorType(), |
| attr, |
| colIndex_, |
| space); |
| |
| if (hbt) |
| generator->getExpGenerator()->linkClause(this, hbt); |
| |
| setChild(0, NULL); |
| |
| hbtMapInfo->codeGenerated(); |
| |
| return 0; |
| } |
| |
| short HbaseTimestampRef::codeGen(Generator * generator) |
| { |
| GenAssert(0, "HbaseTimestampRef::codeGen. Should not reach here."); |
| |
| return 0; |
| } |
| |
| short HbaseVersion::codeGen(Generator * generator) |
| { |
| Attributes ** attr; |
| |
| MapInfo * hbtMapInfo = generator->getMapInfoAsIs(getValueId()); |
| if (hbtMapInfo && hbtMapInfo->isCodeGenerated()) |
| return 0; |
| |
| Space * space = generator->getSpace(); |
| |
| setChild(0, tsVals_); |
| |
| if (generator->getExpGenerator()->genItemExpr(this, &attr, (1 + getArity()), -1) == 1) |
| return 0; |
| |
| ExFunctionHbaseVersion * hbt = |
| new(generator->getSpace()) ExFunctionHbaseVersion |
| (getOperatorType(), |
| attr, |
| colIndex_, |
| space); |
| |
| if (hbt) |
| generator->getExpGenerator()->linkClause(this, hbt); |
| |
| setChild(0, NULL); |
| |
| hbtMapInfo->codeGenerated(); |
| |
| return 0; |
| } |
| |
| short HbaseVersionRef::codeGen(Generator * generator) |
| { |
| GenAssert(0, "HbaseVersionRef::codeGen. Should not reach here."); |
| |
| return 0; |
| } |