| /********************************************************************** |
| // @@@ 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: Param.C |
| * RCS: $Id: Param.cpp,v 1.8 1998/08/10 15:34:04 Exp $ |
| * Description: |
| * |
| * Created: 4/15/95 |
| * Modified: $ $Date: 1998/08/10 15:34:04 $ (GMT) |
| * Language: C++ |
| * Status: $State: Exp $ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| #include <stdlib.h> |
| #include <wchar.h> |
| |
| #include "SqlciCmd.h" |
| #include "str.h" |
| #include "dfs2rec.h" |
| #include "exp_clause_derived.h" |
| #include "IntervalType.h" |
| #include "NLSConversion.h" |
| #include "nawstring.h" |
| |
| extern NAHeap sqlci_Heap; |
| |
| short convDoItMxcs(char * source, |
| Lng32 sourceLen, |
| short sourceType, |
| Lng32 sourcePrecision, |
| Lng32 sourceScale, |
| char * target, |
| Lng32 targetLen, |
| short targetType, |
| Lng32 targetPrecision, |
| Lng32 targetScale, |
| Lng32 flags); |
| |
| Param::Param(char * name_, SetParam *sp_) |
| : name(0), |
| value(0), |
| display_value(0), |
| converted_value(0), |
| nullValue_(0), |
| inSingleByteForm_(TRUE), |
| cs(CharInfo::UnknownCharSet), |
| isQuotedStrWithoutCharSetPrefix_(FALSE), |
| utf16StrLit_(NULL), |
| termCS_(CharInfo::UnknownCharSet) |
| { |
| if (name_) |
| setName(name_); |
| if (sp_) |
| setValue(sp_); |
| } |
| |
| Param::Param(char * name_, char* value_, CharInfo::CharSet x_) |
| : name(0), |
| value(0), |
| display_value(0), |
| converted_value(0), |
| nullValue_(0), |
| inSingleByteForm_(TRUE), |
| cs(CharInfo::UnknownCharSet), |
| isQuotedStrWithoutCharSetPrefix_(FALSE), |
| utf16StrLit_(NULL), |
| termCS_(CharInfo::UnknownCharSet) |
| { |
| if (name_) |
| setName(name_); |
| if (value_) |
| setValue(value_, x_); |
| } |
| |
| Param::Param(char * name_, NAWchar* value_, CharInfo::CharSet x_) |
| : name(0), |
| value(0), |
| display_value(0), |
| converted_value(0), |
| nullValue_(0), |
| inSingleByteForm_(FALSE), |
| cs(CharInfo::UnknownCharSet), |
| isQuotedStrWithoutCharSetPrefix_(FALSE), |
| utf16StrLit_(NULL), |
| termCS_(CharInfo::UnknownCharSet) |
| { |
| if (name_) |
| setName(name_); |
| if (value_) |
| setValue(value_, x_); |
| } |
| |
| Param::~Param() |
| { |
| if (name) { |
| delete [] name; |
| name = 0; |
| }; |
| |
| resetValue_(); |
| } |
| |
| void Param::setName(const char * name_) |
| { |
| if (name) |
| delete [] name; |
| |
| name = new char[strlen(name_) + 1]; |
| strcpy(name, name_); |
| } |
| |
| void Param::resetValue_() |
| { |
| if (value) { |
| delete [] value; |
| value = 0; |
| } |
| |
| if (display_value) { |
| delete [] display_value; |
| display_value = 0; |
| } |
| |
| if (converted_value) { |
| delete [] converted_value; |
| converted_value = 0; |
| }; |
| |
| // it is a non-nullable value |
| if (nullValue_) { |
| delete [] nullValue_; |
| nullValue_ = 0; |
| } |
| |
| if (utf16StrLit_ != (NAWchar*)NULL) { |
| delete [] utf16StrLit_; |
| utf16StrLit_ = (NAWchar*)NULL; |
| } |
| |
| inSingleByteForm_ = TRUE; |
| cs = CharInfo::UnknownCharSet; |
| isQuotedStrWithoutCharSetPrefix_ = FALSE; |
| termCS_ = CharInfo::UnknownCharSet; |
| } |
| |
| void Param::setValue_(const char * value_, CharInfo::CharSet x_) |
| { |
| cs = x_; |
| value = new char[strlen(value_) + 1]; |
| strcpy(value, value_); |
| inSingleByteForm_ = TRUE; |
| } |
| |
| void Param::setValue_(const NAWchar * value_, CharInfo::CharSet x_) |
| { |
| if (x_ == CharInfo::UNICODE && converted_value) { |
| delete [] converted_value; |
| converted_value = 0; |
| }; |
| |
| cs = x_; |
| NAWchar* wvalue = new NAWchar[NAWstrlen(value_) + 1]; |
| NAWstrcpy(wvalue, value_); |
| value = (char*) wvalue; |
| inSingleByteForm_ = FALSE; |
| } |
| |
| void Param::setValue(const char * value_, CharInfo::CharSet x_) |
| { |
| resetValue_(); |
| setValue_(value_, x_); |
| } |
| |
| void Param::setValue(const NAWchar * value_, CharInfo::CharSet x_) |
| { |
| resetValue_(); |
| setValue_(value_, x_); |
| } |
| |
| void Param::setUTF16StrLit (NAWchar *utf16Str) |
| { |
| if (utf16StrLit_) |
| delete [] utf16StrLit_; |
| |
| utf16StrLit_ = new NAWchar [NAWstrlen(utf16Str) + 1]; |
| NAWstrcpy(utf16StrLit_, utf16Str); |
| } |
| |
| void Param::setValue(SetParam* sp_) |
| { |
| resetValue_(); |
| if ( sp_ -> isInSingleByteForm() ) { |
| setValue_(sp_->get_argument(), sp_ -> getCharSet()); |
| } else { |
| setValue_((NAWchar*)(sp_->get_argument()), sp_ -> getCharSet()); |
| } |
| if ( sp_ -> getUTF16ParamStrLit() ) |
| { |
| setUTF16StrLit(sp_ -> getUTF16ParamStrLit()); |
| isQuotedStrWithoutCharSetPrefix_ = sp_ -> isQuotedStrWithoutCharSetPrefix(); |
| setTermCharSet(sp_ -> getTermCharSet()); |
| } |
| } |
| |
| void Param::makeNull() |
| { |
| if (nullValue_) |
| delete [] nullValue_; |
| |
| nullValue_ = new char[2]; |
| *(short *)nullValue_ = -1; |
| } |
| |
| short Param::convertValue(SqlciEnv * sqlci_env, short targetType, |
| Lng32 &targetLen, |
| Lng32 targetPrecision, |
| Lng32 targetScale, |
| Lng32 vcIndLen, |
| ComDiagsArea *&diags) { |
| |
| // get rid of the old converted value |
| if (converted_value) { |
| delete [] converted_value; |
| converted_value = 0; |
| }; |
| |
| short sourceType; |
| Lng32 sourceLen; |
| |
| // set up the source and its length based on the how the value is passed-in. |
| if ( isInSingleByteForm() == FALSE ) { |
| sourceLen = (Lng32)(NAWstrlen((NAWchar*)value) * BYTES_PER_NAWCHAR); |
| switch (getCharSet()) { |
| case CharInfo::UNICODE: |
| sourceType = REC_NCHAR_F_UNICODE; |
| break; |
| |
| case CharInfo::KANJI_MP: |
| case CharInfo::KSC5601_MP: |
| sourceType = REC_BYTE_F_ASCII; // KANJI/KSC passed in as NAWchar* |
| break; |
| |
| default: |
| return SQL_Error; // error case |
| } |
| } else { |
| sourceLen = (Lng32)strlen(value); // for any source in single-byte format |
| sourceType = REC_BYTE_F_ASCII; |
| } |
| |
| char * pParamValue = value; |
| |
| if ( DFS2REC::isAnyCharacter(targetType) ) { |
| |
| if (termCS_ == CharInfo::UnknownCharSet) |
| termCS_ = sqlci_env->getTerminalCharset(); |
| if (cs == CharInfo::UnknownCharSet) |
| { |
| isQuotedStrWithoutCharSetPrefix_ = TRUE; |
| cs = termCS_; |
| } |
| |
| // If the target is CHARACTER and param is set as [_cs_prefix]'...', then |
| // make sure the source is assignment compatible with the target. |
| CharInfo::CharSet targetCharSet = (CharInfo::CharSet)targetScale; |
| if ( targetCharSet == CharInfo::UNICODE ) |
| { |
| if (getUTF16StrLit() == (NAWchar*)NULL) |
| { |
| utf16StrLit_ = new NAWchar [ sourceLen * 2 + 1 ]; // plenty of room |
| Lng32 utf16StrLenInNAWchars = |
| LocaleStringToUnicode(cs/*sourceCS*/, /*sourceStr*/value, sourceLen, |
| utf16StrLit_/*outputBuf*/, sourceLen+1/*outputBufSizeInNAWchars*/, |
| TRUE /* in - NABoolean addNullAtEnd*/); |
| if (sourceLen > 0 && utf16StrLenInNAWchars == 0) |
| return SQL_Error; |
| |
| // ComASSERT(utf16StrLenInNAWchars == NAWstrlen(getUTF16StrLit())); |
| // Resize the NAWchar buffer to save space |
| NAWchar *pNAWcharBuf = new NAWchar [ utf16StrLenInNAWchars + 1 ]; |
| NAWstrncpy (pNAWcharBuf, utf16StrLit_, utf16StrLenInNAWchars + 1); |
| pNAWcharBuf[utf16StrLenInNAWchars] = NAWCHR('\0'); // play it safe |
| delete [] utf16StrLit_; |
| utf16StrLit_ = pNAWcharBuf; // do not deallocate pNAWcharBuf |
| } |
| sourceLen = (Lng32)(NAWstrlen(getUTF16StrLit()) * BYTES_PER_NAWCHAR); |
| // check to see if the parameter utf16 string fits in the target |
| if ( sourceLen > targetLen ) |
| return SQL_Error; |
| |
| pParamValue = (char *)getUTF16StrLit(); |
| sourceType = REC_NCHAR_F_UNICODE; |
| } |
| |
| } else { |
| |
| // MP NCHAR (KANJI/KSC) can not be converted to non-character objects |
| if ( CharInfo::is_NCHAR_MP(cs) ) |
| return SQL_Error; |
| } |
| |
| |
| switch(targetType) { |
| case REC_BOOLEAN: |
| case REC_BIN8_SIGNED: |
| case REC_BIN8_UNSIGNED: |
| case REC_BIN16_SIGNED: |
| case REC_BIN16_UNSIGNED: |
| case REC_BPINT_UNSIGNED: |
| case REC_BIN32_SIGNED: |
| case REC_BIN32_UNSIGNED: |
| case REC_BIN64_SIGNED: |
| case REC_BIN64_UNSIGNED: |
| case REC_DECIMAL_UNSIGNED: |
| case REC_DECIMAL_LSE: |
| case REC_FLOAT32: |
| case REC_FLOAT64: |
| case REC_BYTE_F_ASCII: |
| case REC_BYTE_V_ASCII: |
| case REC_BYTE_V_ASCII_LONG: |
| case REC_NCHAR_F_UNICODE: |
| case REC_NCHAR_V_UNICODE: |
| case REC_BLOB: |
| case REC_CLOB: |
| { |
| char *VCLen = NULL; |
| short VCLenSize = 0; |
| short origTargetType = 0; |
| if ((targetType == REC_BLOB) || (targetType == REC_CLOB)) |
| { |
| // convert the format to a varchar format with 4 bytes of length |
| origTargetType = REC_BLOB; |
| targetType = REC_BYTE_V_ASCII; |
| vcIndLen = sizeof(Int32); |
| } |
| |
| // 5/27/98: added VARCHAR cases |
| if ((targetType == REC_BYTE_V_ASCII) || |
| (targetType == REC_BYTE_V_ASCII_LONG) || |
| (targetType == REC_NCHAR_V_UNICODE)) |
| { |
| // add bytes for variable length field |
| VCLenSize = vcIndLen; //sizeof(short); |
| VCLen = converted_value = new char[targetLen + VCLenSize]; |
| } else |
| converted_value = new char[targetLen]; |
| |
| |
| ex_expr::exp_return_type ok; |
| CharInfo::CharSet TCS = sqlci_env->getTerminalCharset(); |
| CharInfo::CharSet ISOMAPCS = sqlci_env->getIsoMappingCharset(); |
| |
| NAString* tempstr; |
| if ( |
| ( |
| DFS2REC::isAnyCharacter(sourceType) && DFS2REC::isAnyCharacter(targetType) && |
| !(getUTF16StrLit() != NULL && sourceType == REC_NCHAR_F_UNICODE && targetScale == CharInfo::UCS2) && |
| /*source*/cs != targetScale/*i.e., targetCharSet*/ |
| ) && (origTargetType != REC_BLOB) |
| ) |
| |
| { |
| charBuf cbuf((unsigned char*)pParamValue, sourceLen); |
| NAWcharBuf* wcbuf = 0; |
| Int32 errorcode = 0; |
| wcbuf = csetToUnicode(cbuf, 0, wcbuf, |
| cs/*sourceCharSet*/ |
| , errorcode); |
| if (errorcode != 0) return SQL_Error; |
| tempstr = unicodeToChar(wcbuf->data(),wcbuf->getStrLen(), |
| targetScale/*i.e., targetCharSet*/ |
| ); |
| if (tempstr == NULL) |
| return SQL_Error; //Avoid NULL ptr reference if conversion error |
| sourceType = targetType; // we just converted it to the target type |
| sourceLen = tempstr->length(); |
| pParamValue = (char *)tempstr->data(); |
| |
| if ( sourceLen > targetLen ) |
| return SQL_Error; |
| } |
| |
| ok = convDoIt(pParamValue, |
| sourceLen, |
| sourceType, |
| 0, // source Precision |
| targetScale, // new charset we converted to |
| &converted_value[VCLenSize], |
| targetLen, |
| targetType, |
| targetPrecision, |
| targetScale, |
| VCLen, |
| VCLenSize, |
| &sqlci_Heap, |
| &diags); |
| |
| if ( ok != ex_expr::EXPR_OK) |
| { |
| // No need to delete allocated memory before return because class member |
| // converted_value still points to allocated memory that is deleted in |
| // desctructor. |
| return SQL_Error; // error case |
| } |
| |
| }; |
| break; |
| |
| |
| case REC_DATETIME: { |
| |
| char *VCLen = NULL; |
| short VCLenSize = 0; |
| converted_value = new char[targetLen + 1]; |
| |
| UInt32 flags = 0; |
| flags |= CONV_NO_HADOOP_DATE_FIX; |
| |
| ex_expr::exp_return_type ok = convDoIt(value, |
| sourceLen, |
| sourceType, |
| 0, // source Precision |
| 0, // source Scale |
| converted_value, |
| targetLen, |
| targetType, |
| targetPrecision, |
| targetScale, |
| VCLen, |
| VCLenSize, |
| &sqlci_Heap, |
| &diags, |
| CONV_UNKNOWN, |
| NULL, |
| flags); |
| |
| if ( ok != ex_expr::EXPR_OK) |
| { |
| return SQL_Error; // error case |
| } |
| }; |
| break; |
| |
| case REC_INT_YEAR: |
| case REC_INT_MONTH: |
| case REC_INT_YEAR_MONTH: |
| case REC_INT_DAY: |
| case REC_INT_HOUR: |
| case REC_INT_DAY_HOUR: |
| case REC_INT_MINUTE: |
| case REC_INT_HOUR_MINUTE: |
| case REC_INT_DAY_MINUTE: |
| case REC_INT_SECOND: |
| case REC_INT_MINUTE_SECOND: |
| case REC_INT_HOUR_SECOND: |
| case REC_INT_DAY_SECOND: { |
| |
| // convert target back to string. |
| converted_value = new char[targetLen]; |
| Lng32 convFlags = CONV_ALLOW_SIGN_IN_INTERVAL; |
| short ok = |
| convDoItMxcs(value, |
| sourceLen, |
| sourceType, |
| 0, // source Precision |
| 0, // source Scale |
| converted_value, |
| targetLen, |
| targetType, |
| targetPrecision, |
| targetScale, |
| convFlags); |
| |
| if ( ok != 0 ) |
| { |
| // No need to delete allocated memory before return because class member |
| // converted_value still points to allocated memory that is deleted in |
| // desctructor. |
| return SQL_Error; // error case |
| } |
| }; |
| break; |
| |
| case REC_NUM_BIG_UNSIGNED: |
| case REC_NUM_BIG_SIGNED: |
| { |
| converted_value = new char[targetLen]; |
| short ok = |
| convDoItMxcs(value, |
| sourceLen, |
| sourceType, |
| 0, // source Precision |
| 0, // source Scale |
| converted_value, |
| targetLen, |
| targetType, |
| targetPrecision, |
| targetScale, |
| 0); |
| |
| if ( ok != 0 ) |
| { |
| // No need to delete allocated memory before return because class member |
| // converted_value still points to allocated memory that is deleted in |
| // desctructor. |
| return SQL_Error; // error case |
| } |
| |
| }; |
| break; |
| |
| default: |
| break; |
| }; |
| |
| return 0; |
| } |
| |
| short Param::contains(const char * value) const |
| { |
| if (strcmp(name, value) == 0) |
| return -1; |
| else |
| return 0; |
| } |
| |
| char* Param::getDisplayValue(CharInfo::CharSet display_cs) |
| { |
| if ( isInSingleByteForm() == FALSE && getCharSet() == CharInfo::UNICODE ) { |
| |
| if ( display_value == NULL ) |
| { |
| NAWchar* wvalue = (NAWchar*)value; |
| Lng32 wlen = (Lng32)NAWstrlen(wvalue); |
| display_value = new char[wlen+1]; |
| UnicodeStringToLocale(display_cs, wvalue, wlen, |
| display_value, wlen+1, |
| TRUE, // add null at end |
| TRUE // non-convertable char to ? |
| ); |
| } |
| return display_value; |
| |
| } else |
| return getValue(); |
| } |
| |
| ////////////////////////////////////////////////////////////// |
| short SetParam::process(SqlciEnv * sqlci_env) |
| { |
| if (get_arglen() == -1) |
| { |
| // set param to null value |
| Param * param = sqlci_env->get_paramlist()->get(param_name); |
| if (param) |
| param->makeNull(); |
| else |
| { |
| param = new Param(param_name, (char*)0); |
| |
| sqlci_env->get_paramlist()->append(param); |
| param->makeNull(); |
| } |
| } |
| else |
| if (!get_argument()) |
| { |
| /* RESET PARAM command */ |
| if (!param_name) |
| { |
| /* RESET all params */ |
| Param * param = sqlci_env->get_paramlist()->getFirst(); |
| while (param) |
| { |
| sqlci_env->get_paramlist()->remove(param->getName()); |
| delete param; |
| param = sqlci_env->get_paramlist()->getNext(); |
| } |
| } |
| else |
| { |
| Param * param = sqlci_env->get_paramlist()->get(param_name); |
| sqlci_env->get_paramlist()->remove(param_name); |
| delete param; |
| } |
| } |
| else |
| { |
| /* SET PARAM command */ |
| Param * param = sqlci_env->get_paramlist()->get(param_name); |
| if (param) { |
| param->setValue(this); |
| } else |
| { |
| param = new Param(param_name, this); |
| |
| sqlci_env->get_paramlist()->append(param); |
| } |
| } |
| |
| return 0; |
| } |
| |
| SetParam::~SetParam() |
| { |
| if (param_name) |
| delete [] param_name; |
| if (m_convUTF16ParamStrLit) |
| delete [] m_convUTF16ParamStrLit; |
| } |
| |
| void SetParam::setUTF16ParamStrLit(const NAWchar * utf16Str, size_t ucs2StrLen) |
| { |
| if (m_convUTF16ParamStrLit) |
| { |
| delete [] m_convUTF16ParamStrLit; |
| m_convUTF16ParamStrLit = NULL; |
| } |
| m_convUTF16ParamStrLit = new NAWchar[ucs2StrLen + 1]; |
| NAWstrncpy(m_convUTF16ParamStrLit, utf16Str, ucs2StrLen); |
| m_convUTF16ParamStrLit[ucs2StrLen] = L'\0'; |
| } |
| |
| ////////////////////////////////////////////////////////////// |
| short SetPattern::process(SqlciEnv * sqlci_env) |
| { |
| if (!get_argument()) |
| { |
| /* RESET PATTERN command */ |
| if (!pattern_name) |
| { |
| /* RESET all patterns */ |
| Param * pattern = sqlci_env->get_patternlist()->getFirst(); |
| while (pattern) |
| { |
| sqlci_env->get_patternlist()->remove(pattern->getName()); |
| delete pattern; |
| pattern = sqlci_env->get_patternlist()->getNext(); |
| } |
| } |
| else |
| { |
| Param * pattern = sqlci_env->get_patternlist()->get(pattern_name); |
| sqlci_env->get_patternlist()->remove(pattern_name); |
| delete pattern; |
| } |
| } |
| else |
| { |
| /* SET PATTERN command */ |
| Param * pattern = sqlci_env->get_patternlist()->get(pattern_name); |
| if (pattern) |
| { |
| pattern->setValue(get_argument(), sqlci_env->getTerminalCharset()); |
| } |
| else |
| { |
| pattern = new Param(pattern_name, get_argument()); |
| |
| sqlci_env->get_patternlist()->append(pattern); |
| } |
| } |
| |
| return 0; |
| } |
| |
| SetPattern::~SetPattern() |
| { |
| if (pattern_name) |
| delete [] pattern_name; |
| } |
| |