blob: 62b54af7e1ccd21fb4d8213928270bd42c818bce [file] [log] [blame]
/**********************************************************************
// @@@ 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;
}