| /********************************************************************** |
| // @@@ 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: ExExeUtilCli.cpp |
| * Description: |
| * |
| * |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| //#include "ComCextdecs.h" |
| #include "cli_stdh.h" |
| #include "ex_stdh.h" |
| #include "sql_id.h" |
| #include "ComSqlId.h" |
| #include "ExExeUtilCli.h" |
| OutputInfo::OutputInfo(Lng32 numEntries) |
| : numEntries_(numEntries) |
| { |
| |
| ex_assert( numEntries <= MAX_OUTPUT_ENTRIES, "try to fetch more than max columns allowed"); |
| |
| for (Int32 i = 0; i < numEntries_; i++) |
| { |
| data_[i] = NULL; |
| len_[i] = 0; |
| } |
| } |
| |
| void OutputInfo::insert(Lng32 index, char * data) |
| { |
| data_[index] = data; |
| } |
| |
| void OutputInfo::insert(Lng32 index, char * data, Lng32 len) |
| { |
| data_[index] = data; |
| len_[index] = len; |
| } |
| |
| void OutputInfo::insert(Lng32 index, char * data, Lng32 len, Lng32 type, Lng32 *indOffset , Lng32 *varOffset ) |
| { |
| data_[index] = data; |
| len_[index] = len; |
| type_[index] = type; |
| } |
| |
| char * OutputInfo::get(Lng32 index) |
| { |
| if (index < numEntries_) |
| return data_[index]; |
| else |
| return NULL; |
| } |
| |
| short OutputInfo::get(Lng32 index, char* &data, Lng32 &len) |
| { |
| if (index < numEntries_) |
| { |
| data = data_[index]; |
| len = len_[index]; |
| return 0; |
| } |
| |
| return -1; |
| } |
| |
| short OutputInfo::get(Lng32 index, char* &data, Lng32 &len, Lng32 &type, Lng32 *indOffset , Lng32 *varOffset ) |
| { |
| if (index < numEntries_) |
| { |
| data = data_[index]; |
| len = len_[index]; |
| type = type_[index]; |
| return 0; |
| } |
| |
| return -1; |
| } |
| |
| void OutputInfo::dealloc(CollHeap * heap) |
| { |
| for (Int32 i = 0; i < numEntries_; i++) |
| { |
| if(data_[i] != NULL) |
| NADELETEBASIC(data_[i], heap); |
| } |
| } |
| |
| ///////////////////////////////////////////////////////////////// |
| // class ExeCliInterface |
| ///////////////////////////////////////////////////////////////// |
| ExeCliInterface::ExeCliInterface(CollHeap * heap, Int32 isoMapping, |
| ContextCli * currContext, |
| const char *parentQid) |
| : heap_(heap), |
| module_(NULL), |
| stmt_(NULL), |
| sql_src_(NULL), |
| input_desc_(NULL), |
| output_desc_(NULL), |
| rs_input_maxsize_desc_(NULL), |
| outputBuf_(NULL), |
| inputBuf_(NULL), |
| currContext_(currContext), |
| moduleWithCK_(NULL), |
| stmtWithCK_(NULL), |
| sql_src_withCK_(NULL), |
| input_desc_withCK_(NULL), |
| output_desc_withCK_(NULL), |
| outputBuf_withCK_(NULL), |
| rsInputBuffer_(NULL), |
| isoMapping_((Int32)SQLCHARSETCODE_ISO88591), // ISO_MAPPING=ISO88591 |
| parentQid_(parentQid), |
| inputAttrs_(NULL), |
| outputAttrs_(NULL), |
| explainData_(NULL), |
| explainDataLen_(0), |
| flags_(0) |
| { |
| if (parentQid_) |
| { |
| Int32 len = str_len(parentQid_); |
| ex_assert( len >= ComSqlId::MIN_QUERY_ID_LEN, "parentQid too short."); |
| ex_assert( len <= ComSqlId::MAX_QUERY_ID_LEN, "parentQid too long."); |
| ex_assert( !str_cmp(parentQid_, COM_SESSION_ID_PREFIX, 4), |
| "invalid parentQid."); |
| } |
| } |
| |
| ExeCliInterface::~ExeCliInterface() |
| { |
| dealloc(); |
| } |
| |
| Lng32 ExeCliInterface::deallocStuff(SQLMODULE_ID * &module, |
| SQLSTMT_ID * &stmt, |
| SQLDESC_ID * &sql_src, |
| SQLDESC_ID * &input_desc, |
| SQLDESC_ID * &output_desc) |
| { |
| if (sql_src) |
| { |
| SQL_EXEC_DeallocDesc(sql_src); |
| NADELETEBASIC(sql_src, heap_); |
| sql_src = NULL; |
| } |
| |
| if (stmt) |
| { |
| SQL_EXEC_DeallocStmt(stmt); |
| NADELETEBASIC(stmt, heap_); |
| stmt = NULL; |
| } |
| |
| if (input_desc) |
| { |
| SQL_EXEC_DeallocDesc(input_desc); |
| NADELETEBASIC(input_desc, heap_); |
| input_desc = NULL; |
| } |
| |
| if (output_desc) |
| { |
| SQL_EXEC_DeallocDesc(output_desc); |
| NADELETEBASIC(output_desc, heap_); |
| output_desc = NULL; |
| } |
| |
| if (module) |
| { |
| NADELETEBASIC(module, heap_); |
| module = NULL; |
| } |
| |
| if (rsInputBuffer_) |
| { |
| NADELETEBASIC(rsInputBuffer_, heap_); |
| rsInputBuffer_ = NULL; |
| } |
| |
| if (outputAttrs_) |
| { |
| NADELETEBASIC(outputAttrs_, heap_); |
| outputAttrs_ = NULL; |
| } |
| |
| if (outputBuf_) |
| { |
| NADELETEBASIC(outputBuf_, heap_); |
| outputBuf_ = NULL; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::dealloc() |
| { |
| return deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| } |
| |
| void ExeCliInterface::clearGlobalDiags() |
| { |
| SQL_EXEC_ClearDiagnostics(NULL); |
| } |
| |
| Lng32 ExeCliInterface::allocStuff(SQLMODULE_ID * &module, |
| SQLSTMT_ID * &stmt, |
| SQLDESC_ID * &sql_src, |
| SQLDESC_ID * &input_desc, |
| SQLDESC_ID * &output_desc, |
| const char * stmtName |
| ) |
| { |
| Lng32 retcode = 0; |
| deallocStuff(module, stmt, sql_src, input_desc, output_desc); |
| |
| clearGlobalDiags(); |
| |
| module = new(heap_) SQLMODULE_ID; |
| init_SQLMODULE_ID(module); |
| |
| // Allocate a SQL statement |
| stmt = new(heap_) SQLSTMT_ID; |
| if (stmtName) |
| { |
| init_SQLSTMT_ID(stmt, SQLCLI_CURRENT_VERSION, stmt_name, module); |
| stmt->identifier = |
| new(heap_) char[strlen(stmtName) +1]; |
| strcpy((char*)stmt->identifier, stmtName); |
| stmt->identifier_len = (Lng32)strlen(stmtName); |
| } |
| else |
| init_SQLSTMT_ID(stmt, SQLCLI_CURRENT_VERSION, stmt_handle, module); |
| |
| retcode = SQL_EXEC_AllocStmt(stmt, 0); |
| if (retcode < 0) |
| return retcode; |
| |
| // Allocate a descriptor which will hold the SQL statement source |
| sql_src = new(heap_) SQLSTMT_ID; |
| init_SQLDESC_ID(sql_src, SQLCLI_CURRENT_VERSION, desc_handle, module); |
| |
| retcode = SQL_EXEC_AllocDesc(sql_src, 1); |
| if (retcode < 0) |
| return retcode; |
| |
| retcode = SQL_EXEC_SetDescItem(sql_src, 1, SQLDESC_TYPE_FS, |
| REC_BYTE_V_ANSI, 0); |
| if (retcode < 0) |
| return retcode; |
| |
| // Allocate a descriptor which will hold the SQL statement input |
| input_desc = new(heap_) SQLSTMT_ID; |
| init_SQLDESC_ID(input_desc, SQLCLI_CURRENT_VERSION, desc_handle, module); |
| |
| retcode = SQL_EXEC_AllocDesc(input_desc, 1); |
| if (retcode < 0) |
| return retcode; |
| |
| // Allocate a descriptor which will hold the SQL statement output |
| output_desc = new(heap_) SQLSTMT_ID; |
| init_SQLDESC_ID(output_desc, SQLCLI_CURRENT_VERSION, desc_handle, module); |
| |
| retcode = SQL_EXEC_AllocDesc(output_desc, 1); |
| if (retcode < 0) |
| return retcode; |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::prepare(const char * stmtStr, |
| SQLMODULE_ID * module, |
| SQLSTMT_ID * stmt, |
| SQLDESC_ID * sql_src, |
| SQLDESC_ID * input_desc, |
| SQLDESC_ID * output_desc, |
| char ** outputBuf, |
| Queue * outputVarPtrList, |
| char ** inputBuf, |
| Queue * inputVarPtrList, |
| char *uniqueStmtId, |
| Lng32 *uniqueStmtIdLen, |
| SQL_QUERY_COST_INFO *query_cost_info, |
| SQL_QUERY_COMPILER_STATS_INFO *comp_stats_info, |
| NABoolean monitorThis, |
| NABoolean doNotCachePlan) |
| { |
| Lng32 retcode = 0; |
| ULng32 prepFlags = 0; |
| SQL_QUERY_COST_INFO local_query_cost_info; |
| SQL_QUERY_COMPILER_STATS_INFO local_comp_stats_info; |
| |
| if (monitorThis) |
| prepFlags |= PREPARE_MONITOR_THIS_QUERY; |
| |
| if ((currContext_) && (currContext_->getSessionDefaults())) |
| { |
| if(currContext_->getSessionDefaults()->callEmbeddedArkcmp()) |
| prepFlags |= PREPARE_USE_EMBEDDED_ARKCMP; |
| } |
| |
| if (doNotCachePlan) |
| { |
| prepFlags |= PREPARE_NO_TEXT_CACHE; |
| prepFlags |= PREPARE_DONT_CACHE; |
| } |
| |
| retcode = SQL_EXEC_SetDescItem(sql_src, 1, SQLDESC_LENGTH, |
| strlen(stmtStr) + 1, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| retcode = SQL_EXEC_SetDescItem(sql_src, 1, SQLDESC_VAR_PTR, |
| (Long)stmtStr, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_SetDescItem(sql_src, 1, SQLDESC_CHAR_SET, |
| (Int32)SQLCHARSETCODE_UTF8,0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| char parentQid[ComSqlId::MAX_QUERY_ID_LEN + 1]; |
| char *pQidPtr = NULL; |
| if (parentQid_) |
| { |
| // The parentQid_ is a const char *, but the CLI doesn't |
| // want a const char * arg, so convert it safely here. |
| memset(parentQid, 0, sizeof(parentQid)); |
| memcpy(parentQid, parentQid_, ComSqlId::MAX_QUERY_ID_LEN); |
| pQidPtr = parentQid; |
| } |
| retcode = SQL_EXEC_SetStmtAttr(stmt, SQL_ATTR_PARENT_QID, 0, pQidPtr); |
| if (retcode < 0) |
| return retcode; |
| |
| // set parserflags to indicate that this is an internal query from exeutil |
| NABoolean flagWasSetHere = FALSE; |
| if (currContext_) |
| { |
| if (((currContext_->getSqlParserFlags() & 0x20000) == 0) && |
| (NOT notExeUtilInternalQuery())) // this is an exeutil internal query. This is the default. |
| { |
| flagWasSetHere = TRUE; |
| currContext_->setSqlParserFlags(0x20000); // INTERNAL_QUERY_FROM EXEUTIL |
| } |
| } |
| |
| if (uniqueStmtId == NULL) |
| retcode = SQL_EXEC_Prepare2(stmt, sql_src,NULL,0,NULL, |
| (query_cost_info?query_cost_info:&local_query_cost_info), |
| (comp_stats_info?comp_stats_info:&local_comp_stats_info), |
| NULL,0,prepFlags); |
| else |
| { |
| prepFlags |= PREPARE_STANDALONE_QUERY; |
| retcode = SQL_EXEC_Prepare2(stmt, sql_src, NULL, 0, NULL, |
| (query_cost_info?query_cost_info:&local_query_cost_info), |
| (comp_stats_info?comp_stats_info:&local_comp_stats_info), |
| uniqueStmtId, uniqueStmtIdLen, prepFlags); |
| } |
| // reset internal exeutil query parserflags if it was set in this method. |
| if ((currContext_) && (flagWasSetHere)) |
| currContext_->resetSqlParserFlags(0x20000); // INTERNAL_QUERY_FROM EXEUTIL |
| |
| // return the error code that was returned from SQL_EXEC_Prepare |
| if (retcode < 0) |
| return retcode; |
| |
| // clear diagnostics to reset any warnings. |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| Lng32 num_input_entries, num_output_entries; |
| retcode = SQL_EXEC_DescribeStmt(stmt, input_desc, output_desc); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescEntryCount(input_desc, &num_input_entries); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescEntryCount(output_desc, &num_output_entries); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| numInputEntries_ = num_input_entries; |
| numOutputEntries_ = num_output_entries; |
| |
| inputAttrs_ = NULL; |
| outputAttrs_ = NULL; |
| if (numInputEntries_ > 0) |
| inputAttrs_ = (Attrs*) (new(heap_) char[sizeof(Attrs) * numInputEntries_]); |
| |
| if (numOutputEntries_ > 0) |
| outputAttrs_ = (Attrs*) (new(heap_) char[sizeof(Attrs) * numOutputEntries_]); |
| |
| short entry=1; |
| Lng32 datatype = 0; |
| Lng32 datacharset = 0; |
| Lng32 length = 0; |
| Lng32 null_flag = 0; |
| Lng32 dataOffset = -1; |
| Lng32 nullIndOffset = -1; |
| |
| outputDatalen_ = 0; |
| inputDatalen_ = 0; |
| for (; entry <= num_output_entries; entry++) |
| { |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_TYPE_FS, |
| &datatype, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_OCTET_LENGTH, |
| &length, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_NULLABLE, |
| &null_flag, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_CHAR_SET, |
| &datacharset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| outputDatalen_ += length; |
| if (null_flag) |
| outputDatalen_ += SQL_NULL_HDR_SIZE; |
| if (datatype == REC_BYTE_V_ASCII || |
| datatype == REC_BYTE_V_ASCII_LONG || |
| datatype == REC_BYTE_V_DOUBLE) |
| outputDatalen_ += SQL_VARCHAR_HDR_SIZE; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_NULL_IND_OFFSET, |
| &nullIndOffset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_DATA_OFFSET, |
| &dataOffset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| outputAttrs_[entry-1].fsDatatype_ = datatype; |
| outputAttrs_[entry-1].length_ = length; |
| outputAttrs_[entry-1].nullFlag_ = null_flag; |
| outputAttrs_[entry-1].indOffset_ = nullIndOffset; |
| outputAttrs_[entry-1].varOffset_ = dataOffset; |
| } |
| |
| if (outputBuf) |
| { |
| if ((*outputBuf == NULL) && |
| (outputDatalen_ > 0)) |
| *outputBuf = new (heap_) char[outputDatalen_]; |
| |
| Lng32 curpos = 0; |
| for (entry=1; entry <= num_output_entries; entry++) |
| { |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_NULLABLE, |
| &null_flag, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| if (null_flag) |
| { |
| retcode = SQL_EXEC_SetDescItem(output_desc, entry, |
| SQLDESC_IND_PTR, |
| (Long)&(*outputBuf)[curpos],0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| curpos += SQL_NULL_HDR_SIZE; |
| } |
| |
| retcode = SQL_EXEC_SetDescItem(output_desc, entry, |
| SQLDESC_VAR_PTR, |
| (Long)&(*outputBuf)[curpos],0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_OCTET_LENGTH, |
| &length, 0, 0, 0, 0); |
| |
| if (outputVarPtrList) |
| { |
| outputVarPtrList->insert((char*) &(*outputBuf)[curpos]); |
| } |
| |
| curpos += length; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_TYPE_FS, |
| &datatype, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc, entry, |
| SQLDESC_CHAR_SET, |
| &datacharset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| if (datatype == REC_BYTE_V_ASCII || |
| datatype == REC_BYTE_V_ASCII_LONG || |
| datatype == REC_BYTE_V_DOUBLE) |
| curpos += SQL_VARCHAR_HDR_SIZE; |
| |
| } |
| } |
| |
| entry=1; |
| inputDatalen_ = 0; |
| for (; entry <= num_input_entries; entry++) |
| { |
| Lng32 alignedLen = 0; |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_ALIGNED_LENGTH, |
| &alignedLen, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| inputDatalen_ += alignedLen; |
| |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_TYPE_FS, |
| &datatype, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_OCTET_LENGTH, |
| &length, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_NULLABLE, |
| &null_flag, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_NULL_IND_OFFSET, |
| &nullIndOffset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_DATA_OFFSET, |
| &dataOffset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| inputAttrs_[entry-1].fsDatatype_ = datatype; |
| inputAttrs_[entry-1].length_ = length; |
| inputAttrs_[entry-1].nullFlag_ = null_flag; |
| inputAttrs_[entry-1].indOffset_ = nullIndOffset; |
| inputAttrs_[entry-1].varOffset_ = dataOffset; |
| } |
| |
| if (inputBuf) |
| { |
| if ((*inputBuf == NULL) && |
| (inputDatalen_ > 0)) |
| *inputBuf = new (heap_) char[inputDatalen_]; |
| |
| Lng32 curpos = 0; |
| for (entry=1; entry <= num_input_entries; entry++) |
| { |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_NULL_IND_OFFSET, |
| &nullIndOffset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(input_desc, entry, |
| SQLDESC_DATA_OFFSET, |
| &dataOffset, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| if (nullIndOffset >= 0) |
| { |
| retcode = SQL_EXEC_SetDescItem(input_desc, entry, |
| SQLDESC_IND_PTR, |
| (Long)&(*inputBuf)[nullIndOffset],0); |
| if (retcode != SUCCESS) |
| return retcode; |
| } |
| |
| retcode = SQL_EXEC_SetDescItem(input_desc, entry, |
| SQLDESC_VAR_PTR, |
| (Long)&(*inputBuf)[dataOffset],0); |
| if (retcode != SUCCESS) |
| return retcode; |
| } |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::setupExplainData(SQLMODULE_ID * module, |
| SQLSTMT_ID * stmt) |
| { |
| Lng32 retcode = 0; |
| |
| if (explainData_) |
| NADELETEBASIC(explainData_, getHeap()); |
| |
| explainData_ = NULL; |
| explainDataLen_ = 0; |
| |
| // get explain fragment. |
| explainDataLen_ = 50000; // start with 50K bytes |
| Int32 retExplainLen = 0; |
| explainData_ = new(getHeap()) char[explainDataLen_+1]; |
| retcode = SQL_EXEC_GetExplainData(stmt, |
| explainData_, explainDataLen_+1, |
| &retExplainLen |
| ); |
| if (retcode == -CLI_GENCODE_BUFFER_TOO_SMALL) |
| { |
| NADELETEBASIC(explainData_, getHeap()); |
| |
| explainDataLen_ = retExplainLen; |
| explainData_ = new(getHeap()) char[explainDataLen_ + 1]; |
| |
| retcode = SQL_EXEC_GetExplainData(stmt, |
| explainData_, explainDataLen_+1, |
| &retExplainLen |
| ); |
| } |
| |
| if (retcode != SUCCESS) |
| { |
| NADELETEBASIC(explainData_, getHeap()); |
| explainData_ = NULL; |
| explainDataLen_ = 0; |
| |
| return retcode; |
| } |
| |
| explainDataLen_ = retExplainLen; |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::setupExplainData() |
| { |
| return setupExplainData(module_, stmt_); |
| } |
| |
| |
| Lng32 ExeCliInterface::exec(char * inputBuf, Lng32 inputBufLen) |
| { |
| Lng32 retcode = 0; |
| |
| if (! stmt_) |
| { |
| return -CLI_STMT_NOT_EXISTS; |
| } |
| |
| // set parserflags to indicate that this is an internal query from exeutil |
| NABoolean flagWasSetHere = FALSE; |
| if (currContext_) |
| { |
| if (((currContext_->getSqlParserFlags() & 0x20000) == 0) && |
| (NOT notExeUtilInternalQuery())) // this is an exeutil internal query. This is the default. |
| { |
| flagWasSetHere = TRUE; |
| currContext_->setSqlParserFlags(0x20000); // INTERNAL_QUERY_FROM EXEUTIL |
| } |
| } |
| |
| if ((inputBuf) && (inputBuf_) && (inputDatalen_ > 0) && (inputBufLen > 0)) |
| memcpy(inputBuf_, inputBuf, MINOF(inputDatalen_, inputBufLen)); |
| |
| retcode = SQL_EXEC_Exec(stmt_, input_desc_, 0); |
| |
| // reset internal exeutil query parserflags if it was set in this method. |
| if ((currContext_) && (flagWasSetHere)) |
| currContext_->resetSqlParserFlags(0x20000); // INTERNAL_QUERY_FROM EXEUTIL |
| |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::fetch() |
| { |
| Lng32 retcode = 0; |
| |
| retcode = SQL_EXEC_Fetch(stmt_, output_desc_, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| return retcode; |
| } |
| |
| //if indicator pointer is NULL, do not retrieve the indicator |
| //the datatype SQLTYPECODE... is added (the others did not work) |
| Lng32 ExeCliInterface::getPtrAndLen(short entry, char* &ptr, Lng32 &len, short**ind) |
| { |
| Long data_addr; |
| Lng32 datatype = 0; |
| Lng32 retcode; |
| Long ind_addr; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc_, entry, |
| SQLDESC_VAR_PTR, |
| &data_addr, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc_, entry, |
| SQLDESC_IND_PTR , |
| &ind_addr, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| if (ind != NULL) |
| *ind = (short*)ind_addr; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc_, entry, |
| SQLDESC_TYPE, |
| &datatype, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc_, entry, |
| SQLDESC_OCTET_LENGTH, |
| &len, 0, 0, 0, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| short *nullIndPtr = (short *)ind_addr; |
| if (nullIndPtr && *nullIndPtr < 0) |
| { |
| // without this test, when "showddl component sql_operations" |
| // ran some child query which returned a nullable column |
| // with a SQL NULL value, junk from data_addr was interpreted |
| // as a length and the caller of this method tried to allocate |
| // too many bytes. |
| len = 0; |
| } |
| else |
| if (datatype == REC_BYTE_V_ASCII || |
| datatype == REC_BYTE_V_ASCII_LONG || |
| datatype == REC_BYTE_V_DOUBLE || |
| datatype == SQLTYPECODE_VARCHAR_WITH_LENGTH || |
| datatype == SQLTYPECODE_VARCHAR_LONG || |
| datatype == SQLTYPECODE_BLOB || |
| datatype == SQLTYPECODE_CLOB |
| ) |
| { |
| |
| // Depending on value of len, first 2 or 4 bytes of data indicate |
| // the actual length -- adjust data and length |
| if (len & 0xFFFF8000) |
| { |
| Lng32 VClen; |
| str_cpy_all((char*)&VClen, (char*)data_addr, sizeof(Lng32)); |
| data_addr += sizeof(Lng32); |
| len = VClen; |
| } |
| else |
| { |
| short VClen; |
| str_cpy_all((char*)&VClen, (char*)data_addr, sizeof(short)); |
| data_addr += sizeof(short); |
| len = VClen; |
| } |
| } |
| |
| ptr = (char*)data_addr; |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::getHeadingAndLen(short entry, char* heading, Lng32 &len) |
| { |
| Lng32 retcode; |
| |
| len = 0; |
| retcode = SQL_EXEC_GetDescItem(output_desc_, entry, |
| SQLDESC_HEADING, |
| 0, heading, |
| ComMAX_1_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES, &len, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| if (len == 0) |
| { |
| retcode = SQL_EXEC_GetDescItem(output_desc_, entry, |
| SQLDESC_NAME, |
| 0, heading, |
| ComMAX_1_PART_EXTERNAL_UTF8_NAME_LEN_IN_BYTES/*CAT_MAX_HEADING_LEN*/, &len, 0); |
| if (retcode != SUCCESS) |
| return retcode; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::getNumEntries(Lng32 &numInput, Lng32 &numOutput) |
| { |
| Lng32 retcode = 0; |
| |
| retcode = SQL_EXEC_GetDescEntryCount(input_desc_, &numInput); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = SQL_EXEC_GetDescEntryCount(output_desc_, &numOutput); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| return retcode; |
| } |
| |
| |
| Lng32 ExeCliInterface::getAttributes(short entry, NABoolean forInput, |
| Lng32 &fsDatatype, Lng32 &length, |
| Lng32 *indOffset, Lng32 *varOffset) |
| { |
| Lng32 retcode = 0; |
| |
| if (forInput) |
| { |
| fsDatatype = inputAttrs_[entry-1].fsDatatype_; |
| length = inputAttrs_[entry-1].length_; |
| if (indOffset) |
| *indOffset = inputAttrs_[entry-1].indOffset_; |
| if (varOffset) |
| *varOffset = inputAttrs_[entry-1].varOffset_; |
| } |
| else |
| { |
| fsDatatype = outputAttrs_[entry-1].fsDatatype_; |
| length = outputAttrs_[entry-1].length_; |
| if (indOffset) |
| *indOffset = outputAttrs_[entry-1].indOffset_; |
| if (varOffset) |
| *varOffset = outputAttrs_[entry-1].varOffset_; |
| } |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::getDataOffsets(short entry, Lng32 forInput, |
| Lng32 *indOffset, Lng32 *varOffset) |
| { |
| Lng32 temp; |
| if (forInput) |
| { |
| if (inputAttrs_ && inputAttrs_[entry-1].varOffset_ && inputAttrs_[entry-1].indOffset_) |
| { |
| *varOffset = inputAttrs_[entry-1].varOffset_; |
| *indOffset = inputAttrs_[entry-1].indOffset_; |
| } |
| else |
| { |
| return getAttributes(entry, forInput, temp, temp, |
| indOffset, varOffset); |
| } |
| } |
| else |
| { |
| return getAttributes(entry, forInput, temp, temp, |
| indOffset, varOffset); |
| } |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::getStmtAttr(char * stmtName, Lng32 attrName, |
| Lng32 * numeric_value, char * string_value) |
| { |
| Lng32 retcode = 0; |
| |
| SQLMODULE_ID module; |
| init_SQLMODULE_ID(&module); |
| |
| char stmtNameBuf[400]; |
| SQLSTMT_ID stmt; |
| init_SQLSTMT_ID(&stmt, SQLCLI_CURRENT_VERSION, stmt_name, &module); |
| stmt.identifier = stmtNameBuf; |
| strcpy((char*)stmt.identifier, stmtName); |
| stmt.identifier_len = (Lng32)strlen(stmtName); |
| |
| retcode = SQL_EXEC_GetStmtAttr(&stmt, attrName, numeric_value, string_value, |
| 0, NULL); |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::close() |
| { |
| Lng32 retcode = 0; |
| |
| if (stmt_) |
| { |
| retcode = SQL_EXEC_CloseStmt(stmt_); |
| if (retcode != SUCCESS) |
| return retcode; |
| } |
| |
| return retcode; |
| } |
| |
| |
| |
| Lng32 ExeCliInterface::executeImmediatePrepare(const char * stmtStr, |
| char * outputBuf, |
| Lng32 * outputBufLen, |
| Int64 * rowsAffected, |
| NABoolean monitorThis, |
| char * stmtName |
| ) |
| { |
| Lng32 retcode = 0; |
| if (outputBufLen) |
| *outputBufLen = 0; |
| |
| retcode = allocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_, |
| stmtName); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = prepare(stmtStr, module_, stmt_, sql_src_, |
| input_desc_, output_desc_, &outputBuf,NULL,&inputBuf_, |
| NULL,NULL,NULL,NULL,NULL,monitorThis); |
| if (retcode < 0) |
| { |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| return retcode; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::executeImmediatePrepare2(const char * stmtStr, |
| char *uniqueStmtId, |
| Lng32 *uniqueStmtIdLen, |
| SQL_QUERY_COST_INFO *query_cost_info, |
| SQL_QUERY_COMPILER_STATS_INFO *comp_stats_info, |
| char * outputBuf, |
| Lng32 * outputBufLen, |
| Int64 * rowsAffected, |
| NABoolean monitorThis |
| ) |
| { |
| Lng32 retcode = 0; |
| |
| if (outputBufLen) |
| *outputBufLen = 0; |
| |
| retcode = allocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = prepare(stmtStr, module_, stmt_, sql_src_, |
| input_desc_, output_desc_, &outputBuf, NULL, NULL, NULL, |
| uniqueStmtId, uniqueStmtIdLen, query_cost_info, comp_stats_info,monitorThis); |
| if (retcode < 0) |
| { |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| return retcode; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::executeImmediateExec(const char * stmtStr, |
| char * outputBuf, |
| Lng32 * outputBufLen, |
| NABoolean nullTerminate, |
| Int64 * rowsAffected, |
| ComDiagsArea **diagsArea) |
| { |
| Lng32 retcode = 0; |
| Lng32 diagsCount = 0; |
| |
| retcode = exec(); |
| if (retcode < 0) |
| { |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| goto ExecReturn; |
| } |
| |
| retcode = fetch(); |
| if (retcode < 0) |
| { |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| goto ExecReturn; |
| } |
| |
| if ((outputBuf) && |
| (outputBufLen)) |
| { |
| *outputBufLen = 0; |
| if (retcode != 100) |
| { |
| char * ptr; |
| Lng32 len; |
| getPtrAndLen(1, ptr, len); |
| str_cpy_all(outputBuf, ptr, len); |
| |
| if (nullTerminate) |
| outputBuf[len] = 0; |
| *outputBufLen = len; |
| } |
| } |
| |
| Lng32 rc; |
| if (retcode >= 0) |
| { |
| if (rowsAffected) |
| { |
| Int64 tmpRowsAffected = 0; |
| rc = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_ROW_COUNT, |
| &tmpRowsAffected, NULL, |
| 0, NULL); |
| |
| if (rc == EXE_NUMERIC_OVERFLOW) |
| { |
| GetRowsAffected(rowsAffected); |
| } |
| else |
| *rowsAffected = tmpRowsAffected; |
| } |
| rc = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_NUMBER, |
| &diagsCount, NULL, 0, NULL); |
| // No need to passback the warnings of SQL_NO_DATA (100) |
| if (retcode == 100) |
| diagsCount--; |
| } |
| ExecReturn: |
| if (retcode < 0 || diagsCount > 0) |
| { |
| if (diagsArea != NULL) |
| { |
| if (*diagsArea == NULL) |
| *diagsArea = ComDiagsArea::allocate(heap_); |
| rc = SQL_EXEC_MergeDiagnostics_Internal(**diagsArea); |
| } |
| // if diagsArea is not passed in, retain the diagnostics info |
| // in ContextCli for it to be retrieved later |
| // But, deallocate the statement |
| else |
| { |
| rc = close(); |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| return retcode; |
| } |
| } |
| rc = close(); |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| clearGlobalDiags(); |
| return retcode; |
| } |
| // When the globalDiags is not null, errors and warnings are |
| // passed to the caller. If *globalsDiags points to NULL, |
| // allocate ComDiagsArea and pass back the error or warnings |
| // to the caller. |
| // |
| // If *globalDiags points to ComDiagsArea already, pass back |
| // the diagnostics conditions back to the caller after executing |
| // the stmtStr along with new errors or warnings. |
| Lng32 ExeCliInterface::executeImmediate(const char * stmtStr, |
| char * outputBuf, |
| Lng32 * outputBufLen, |
| NABoolean nullTerminate, |
| Int64 * rowsAffected, |
| NABoolean monitorThis, |
| ComDiagsArea **globalDiags) |
| { |
| Lng32 retcode = 0; |
| |
| ComDiagsArea * tempDiags = NULL; |
| if (globalDiags != NULL && *globalDiags != NULL && (*globalDiags)->getNumber() > 0) |
| { |
| tempDiags = ComDiagsArea::allocate(heap_); |
| tempDiags->mergeAfter(**globalDiags); |
| } |
| |
| clearGlobalDiags(); |
| outputBuf_ = NULL; |
| inputBuf_ = NULL; |
| retcode = executeImmediatePrepare(stmtStr, |
| (nullTerminate ? outputBuf_ : outputBuf), |
| outputBufLen, |
| rowsAffected,monitorThis); |
| if (retcode < 0) |
| goto ExecuteImmediateReturn; |
| retcode = executeImmediateExec(stmtStr, |
| outputBuf, outputBufLen, |
| nullTerminate, |
| rowsAffected, |
| globalDiags); |
| ExecuteImmediateReturn: |
| if ((globalDiags)) |
| { |
| // Allocate the diagnostics area if needed |
| // and populate the diagnostics conditions |
| if (*globalDiags == NULL && retcode != 0 && retcode != 100) { |
| *globalDiags = ComDiagsArea::allocate(getHeap()); |
| SQL_EXEC_MergeDiagnostics_Internal(**globalDiags); |
| } |
| // populate the diagnostics conditons passed in |
| if (tempDiags) |
| (*globalDiags)->mergeAfter(*tempDiags); |
| } |
| |
| if (tempDiags) |
| tempDiags->deAllocate(); |
| return retcode; |
| } |
| |
| short ExeCliInterface::fetchRowsPrologue(const char * sqlStrBuf, |
| NABoolean noExec, |
| NABoolean monitorThis, |
| char * stmtName) |
| { |
| Lng32 retcode; |
| |
| clearGlobalDiags(); |
| |
| retcode = allocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_, |
| stmtName); |
| if (retcode < 0) |
| { |
| //ex_assert(0, "Error in fetchRows"); |
| return (short)retcode; |
| } |
| |
| outputBuf_ = NULL; |
| inputBuf_ = NULL; |
| retcode = prepare(sqlStrBuf, module_, stmt_, sql_src_, |
| input_desc_, output_desc_, &outputBuf_, NULL, |
| &inputBuf_, NULL,NULL,NULL,NULL,NULL,monitorThis); |
| if (retcode < 0) |
| { |
| //ex_assert(0, "Error in fetchRows"); |
| return (short)retcode; |
| } |
| |
| if (NOT noExec) |
| { |
| retcode = exec(); |
| if (retcode < 0) |
| { |
| //ex_assert(0, "Error in fetchRows"); |
| return (short)retcode; |
| } |
| } |
| |
| return 0; |
| } |
| |
| short ExeCliInterface::fetchRowsEpilogue(const char * sqlStrBuf, |
| NABoolean noClose) |
| { |
| if (NOT noClose) |
| close(); |
| |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| |
| if (NOT noClose) |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| return 0; |
| } |
| |
| short ExeCliInterface::initializeInfoList(Queue* &infoList, |
| NABoolean infoListIsOutputInfo) |
| { |
| if (infoList) |
| { |
| infoList->position(); |
| while (NOT infoList->atEnd()) |
| { |
| if (infoListIsOutputInfo) |
| { |
| OutputInfo * r = (OutputInfo*)infoList->getCurr(); |
| r->dealloc(getHeap()); |
| } |
| else |
| { |
| char * c = (char*)infoList->getCurr(); |
| NADELETEBASIC(c, getHeap()); |
| } |
| |
| infoList->advance(); |
| } |
| NADELETE(infoList, Queue, getHeap()); |
| } |
| |
| infoList = new(getHeap()) Queue(getHeap()); |
| |
| return 0; |
| } |
| |
| short ExeCliInterface::fetchAllRows(Queue * &infoList, |
| const char * query, |
| Lng32 inNumOutputEntries, |
| NABoolean varcharFormat, |
| NABoolean monitorThis, |
| NABoolean initInfoList) |
| { |
| short rc = 0; |
| |
| Lng32 numOutputEntries = inNumOutputEntries; |
| |
| if (initInfoList) |
| { |
| rc = initializeInfoList(infoList, TRUE); |
| if (rc < 0) |
| { |
| return rc; |
| } |
| } |
| |
| rc = fetchRowsPrologue(query,FALSE,monitorThis); |
| if (rc < 0) |
| { |
| return rc; |
| } |
| |
| NABoolean rowsFound = FALSE; |
| while ((rc >= 0) && |
| (rc != 100)) |
| { |
| rc = (short)fetch(); |
| if (rc < 0) |
| { |
| fetchRowsEpilogue(0, TRUE); |
| |
| return rc; |
| } |
| |
| if (rc == 100) |
| continue; |
| |
| rowsFound = TRUE; |
| if (numOutputEntries == -1) |
| { |
| char * ob = new(getHeap()) char[outputDatalen()]; |
| str_cpy_all(ob, outputBuf(), |
| outputDatalen()); |
| |
| infoList->insert(ob); |
| } |
| else |
| { |
| if (numOutputEntries == 0) |
| numOutputEntries = numOutputEntries_; |
| |
| OutputInfo * oi = new(getHeap()) OutputInfo(numOutputEntries); |
| |
| for (Int32 j = 0; j < numOutputEntries; j++) |
| { |
| char * ptr, *r; |
| Lng32 len; |
| Lng32 type; |
| short nulind=0; |
| short *indaddr=&nulind; |
| short **ind=&indaddr; |
| getAttributes(j+1, FALSE, type, len, NULL, NULL); |
| getPtrAndLen(j+1, ptr, len, ind); |
| NABoolean nullableCol = TRUE, isNullVal = FALSE; |
| if(*ind == NULL) // It is not a nullable value |
| isNullVal = FALSE; |
| else |
| { |
| if( ((char*)*ind)[0] == -1 ) // NULL value |
| isNullVal = TRUE; |
| } |
| |
| if(isNullVal) |
| { |
| oi->insert(j, NULL, 0, type); |
| } |
| else |
| { |
| NABoolean nullTerminate = |
| DFS2REC::is8bitCharacter(outputAttrs_[j].fsDatatype_); |
| |
| r = new(getHeap()) char |
| [(varcharFormat ? SQL_VARCHAR_HDR_SIZE : 0) |
| + len + (nullTerminate ? 1 : 0)]; |
| if (varcharFormat) |
| { |
| *(short*)r = (short)len; |
| str_cpy_all(&r[SQL_VARCHAR_HDR_SIZE], ptr, len); |
| |
| if (nullTerminate) |
| r[SQL_VARCHAR_HDR_SIZE + len] = 0; |
| } |
| else |
| { |
| str_cpy_all(r, ptr, len); |
| if (nullTerminate) |
| r[len] = 0; |
| } |
| oi->insert(j, r, len, type); |
| } |
| } |
| |
| infoList->insert(oi); |
| } |
| } // while |
| |
| rc = fetchRowsEpilogue(0); |
| if (rc < 0) |
| { |
| return rc; |
| } |
| |
| if (NOT rowsFound) |
| rc = 100; |
| |
| return rc; |
| } |
| |
| short ExeCliInterface::clearExecFetchClose(char * inputBuf, |
| Lng32 inputBufLen, |
| |
| // ptr to buf where output values will be copied to. |
| // Caller need to allocate this. |
| char * outputBuf, |
| Lng32 * outputBufLen) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = exec(inputBuf, inputBufLen); |
| if (retcode < 0) |
| { |
| return (short)retcode; |
| } |
| |
| retcode = fetch(); |
| if (retcode < 0) |
| { |
| return (short)retcode; |
| } |
| |
| if ((outputBuf) && |
| (outputBufLen)) |
| { |
| *outputBufLen = 0; |
| if (retcode != 100) |
| { |
| char * currPtr = outputBuf; |
| for (Int32 j = 0; j < numOutputEntries_; j++) |
| { |
| char * ptr; |
| Lng32 len; |
| getPtrAndLen(j+1, ptr, len); |
| |
| str_cpy_all(currPtr, ptr, len); |
| currPtr += len; |
| |
| *outputBufLen += len; |
| } |
| } |
| } |
| close(); |
| if (retcode == 100) |
| fetchRowsEpilogue(NULL, TRUE); |
| return (short)retcode; |
| } |
| |
| short ExeCliInterface::clearExecFetchCloseOpt(char * inputBuf, |
| Lng32 inputBufLen, |
| |
| // ptr to buf where output values will be copied to. |
| // Caller need to allocate this. |
| char * outputBuf, |
| Lng32 * outputBufLen, |
| Int64 * rowsAffected) |
| { |
| Lng32 retcode = 0; |
| |
| if (inputBuf) |
| { |
| if (inputDatalen_ < inputBufLen) |
| { |
| // input data will not fit in inputBuf_. |
| // return error. |
| return -EXE_STRING_OVERFLOW; |
| } |
| |
| str_cpy_all(inputBuf_, inputBuf, inputBufLen); |
| } |
| |
| if (rowsAffected) |
| *rowsAffected = 0; |
| |
| retcode = SQL_EXEC_ClearExecFetchClose( |
| stmt_, |
| (numInputEntries_ > 0 ? input_desc_ : NULL), |
| (numOutputEntries_ > 0 ? output_desc_ : NULL), |
| 0, 0, 0); |
| |
| if ((retcode == 0) || |
| ((retcode >= 0) && (retcode != 100))) |
| { |
| if ((numOutputEntries_ > 0) && |
| (outputBuf) && |
| (outputBufLen)) |
| { |
| *outputBufLen = 0; |
| |
| char * currPtr = outputBuf; |
| for (Int32 j = 0; j < numOutputEntries_; j++) |
| { |
| char * ptr; |
| Lng32 len; |
| getPtrAndLen(j+1, ptr, len); |
| |
| str_cpy_all(currPtr, ptr, len); |
| currPtr += len; |
| |
| *outputBufLen += len; |
| } |
| |
| if (rowsAffected) |
| { |
| *rowsAffected = 1; |
| } |
| } // values being returned |
| else if (rowsAffected) |
| { |
| Lng32 tmpRowsAffected = 0; |
| retcode = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_ROW_COUNT, |
| &tmpRowsAffected, NULL, |
| 0, NULL); |
| |
| if(retcode == EXE_NUMERIC_OVERFLOW) // rowsAffected > LONG_MAX |
| { |
| GetRowsAffected(rowsAffected); |
| } |
| else |
| *rowsAffected = (Int64)tmpRowsAffected; |
| } // rowsAffected |
| } |
| |
| return (short)retcode; |
| } |
| |
| Lng32 ExeCliInterface::executeImmediateCEFC(const char * stmtStr, |
| char * inputBuf, |
| Lng32 inputBufLen, |
| char * outputBuf, |
| Lng32 * outputBufLen, |
| Int64 * rowsAffected |
| ) |
| { |
| Lng32 retcode = 0; |
| |
| |
| clearGlobalDiags(); |
| |
| outputBuf_ = NULL; |
| inputBuf_ = NULL; |
| retcode = executeImmediatePrepare(stmtStr, |
| outputBuf, |
| outputBufLen, |
| rowsAffected); |
| if (retcode < 0) |
| goto ExecuteImmediateCEFCReturn; |
| |
| retcode = clearExecFetchCloseOpt(inputBuf, inputBufLen, NULL, NULL, rowsAffected); |
| |
| ExecuteImmediateCEFCReturn: |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::cwrsAllocStuff(SQLMODULE_ID * &module, |
| SQLSTMT_ID * &stmt, |
| SQLDESC_ID * &sql_src, |
| SQLDESC_ID * &input_desc, |
| SQLDESC_ID * &output_desc, |
| SQLDESC_ID * &rs_input_maxsize_desc, |
| const char * stmtName |
| ) |
| { |
| Lng32 retcode = 0; |
| |
| retcode = cwrsDeallocStuff(module, |
| stmt, |
| sql_src, |
| input_desc, |
| output_desc, |
| rs_input_maxsize_desc); |
| if (retcode < 0) |
| { |
| return (short)retcode; |
| } |
| |
| retcode = allocStuff(module, |
| stmt, |
| sql_src, |
| input_desc, |
| output_desc); |
| if (retcode < 0) |
| { |
| return (short)retcode; |
| } |
| |
| // Allocate a descriptor to set input array maximum size |
| rs_input_maxsize_desc = new(heap_) SQLSTMT_ID; |
| init_SQLDESC_ID(rs_input_maxsize_desc, SQLCLI_CURRENT_VERSION, desc_handle, module); |
| |
| retcode = SQL_EXEC_AllocDesc(rs_input_maxsize_desc, 1); |
| if (retcode < 0) |
| return retcode; |
| |
| retcode = SQL_EXEC_SetDescItem(rs_input_maxsize_desc, 1, SQLDESC_TYPE, |
| SQLTYPECODE_INTEGER, NULL); |
| if (retcode < 0) |
| return retcode; |
| |
| retcode = SQL_EXEC_SetDescItem( rs_input_maxsize_desc, |
| 1, // entry #1, attr value. |
| SQLDESC_VAR_PTR, // what to set - host var addr |
| (long) &rsMaxsize_, // Notice that output from CLI |
| // will be read from host var |
| // rowset_size. |
| NULL); |
| |
| retcode = SQL_EXEC_SetStmtAttr(stmt, |
| SQL_ATTR_INPUT_ARRAY_MAXSIZE, |
| rsMaxsize_, |
| NULL); |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::cwrsDeallocStuff( |
| SQLMODULE_ID * &module, |
| SQLSTMT_ID * &stmt, |
| SQLDESC_ID * &sql_src, |
| SQLDESC_ID * &input_desc, |
| SQLDESC_ID * &output_desc, |
| SQLDESC_ID * &rs_input_maxsize_desc) |
| { |
| deallocStuff(module, stmt, sql_src, input_desc, output_desc); |
| |
| if (rs_input_maxsize_desc) |
| { |
| SQL_EXEC_DeallocDesc(rs_input_maxsize_desc); |
| NADELETEBASIC(rs_input_maxsize_desc, heap_); |
| rs_input_maxsize_desc = NULL; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::cwrsPrepare(const char * stmtStr, |
| Lng32 rs_maxsize, NABoolean monitorThis) |
| { |
| Lng32 retcode = 0; |
| |
| rsMaxsize_ = rs_maxsize; |
| retcode = cwrsAllocStuff(module_, stmt_, sql_src_, |
| input_desc_, output_desc_, |
| rs_input_maxsize_desc_); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| retcode = prepare(stmtStr, module_, stmt_, sql_src_, |
| input_desc_, output_desc_, NULL,NULL,NULL,NULL, |
| NULL,NULL,NULL,NULL,monitorThis); |
| if (retcode < 0) |
| { |
| cwrsDeallocStuff(module_, stmt_, sql_src_, |
| input_desc_, output_desc_, |
| rs_input_maxsize_desc_); |
| return retcode; |
| } |
| |
| numQuadFields_ = numInputEntries_;// + 1; |
| quadFields_ = (SQLCLI_QUAD_FIELDS*) |
| new (heap_) char[sizeof(SQLCLI_QUAD_FIELDS) * numQuadFields_]; |
| |
| rsInputBuffer_ = new(heap_) char[rsMaxsize_ * inputDatalen_]; |
| |
| Lng32 fsDatatype; |
| Lng32 length; |
| Lng32 indOffset = 0; |
| Lng32 varOffset = 0; |
| |
| quadFields_[0].var_layout = 0; |
| quadFields_[0].var_ptr = (void *)&currRSrow_; |
| quadFields_[0].ind_layout = 0; |
| quadFields_[0].ind_ptr = NULL; |
| |
| Lng32 currOffset = 0; |
| for (Lng32 entry = 2; entry <= numInputEntries_; entry++) |
| { |
| getAttributes(entry, TRUE, |
| fsDatatype, length, |
| &indOffset, &varOffset); |
| |
| quadFields_[entry-1].var_layout = length; |
| quadFields_[entry-1].var_ptr = (void*)&rsInputBuffer_[currOffset]; |
| quadFields_[entry-1].ind_layout = 0; |
| quadFields_[entry-1].ind_ptr = NULL; |
| |
| currOffset += length * rsMaxsize_; |
| } |
| |
| currRSrow_ = 0; |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::cwrsExec( |
| char * inputRow, |
| Int32 inputRowLen, |
| Int64 * rowsAffected) |
| { |
| Lng32 retcode = 0; |
| |
| Int32 rowset_status[1]; // Has no functionality currently. |
| //However it is part of RowsetSetDesc API |
| |
| if ((inputRow) && (currRSrow_ < rsMaxsize_)) |
| { |
| Lng32 fsDatatype; |
| Lng32 length; |
| Lng32 indOffset = 0; |
| Lng32 varOffset = 0; |
| |
| for (Lng32 entry = 2; entry <= numInputEntries_; entry++) |
| { |
| getAttributes(entry, TRUE, |
| fsDatatype, length, |
| &indOffset, &varOffset); |
| |
| str_cpy_all((char*)((long)(quadFields_[entry-1].var_ptr) + |
| currRSrow_*length), |
| &inputRow[varOffset], length); |
| } |
| |
| currRSrow_++; |
| return 0; |
| } |
| |
| if ((inputRow == NULL) && (currRSrow_ == 0)) |
| return 0; |
| |
| retcode = SQL_EXEC_SETROWSETDESCPOINTERS(input_desc_, |
| currRSrow_, |
| rowset_status, |
| 1, |
| numQuadFields_, |
| quadFields_); |
| if (retcode < 0) |
| return retcode; |
| |
| retcode = exec(); |
| if (retcode < 0) |
| return retcode; |
| |
| retcode = fetch(); |
| if (retcode < 0) |
| return retcode; |
| |
| if (retcode >= 0) |
| { |
| if (rowsAffected) |
| { |
| Lng32 tmpRowsAffected = 0; |
| retcode = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_ROW_COUNT, |
| &tmpRowsAffected, NULL, |
| 0, NULL); |
| |
| if(retcode == EXE_NUMERIC_OVERFLOW) // rowsAffected > LONG_MAX |
| { |
| GetRowsAffected(rowsAffected); |
| } |
| else |
| *rowsAffected = (Int64)tmpRowsAffected; |
| |
| retcode = 0; |
| } |
| } |
| |
| retcode = close(); |
| |
| currRSrow_ = 0; |
| |
| // current input row has not been moved to the rowset buffer. |
| // move the input row to the rowset buffer |
| return cwrsExec(inputRow, inputRowLen, rowsAffected); |
| } |
| |
| Lng32 ExeCliInterface::cwrsClose(Int64 * rowsAffected) |
| { |
| Lng32 retcode = 0; |
| |
| if (rowsAffected) |
| *rowsAffected = 0; |
| |
| retcode = cwrsExec(NULL, 0, rowsAffected); |
| |
| Lng32 retcode2 = cwrsDeallocStuff(module_, stmt_, sql_src_, |
| input_desc_, output_desc_, |
| rs_input_maxsize_desc_); |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::rwrsPrepare(const char * stmtStr, Lng32 rs_maxsize,NABoolean monitorThis) |
| { |
| Lng32 retcode = 0; |
| |
| rsMaxsize_ = rs_maxsize; |
| retcode = allocStuff(module_, stmt_, sql_src_, |
| input_desc_, output_desc_); |
| if (retcode != SUCCESS) |
| return retcode; |
| |
| /* |
| retcode = SQL_EXEC_SetStmtAttr(stmt_, |
| SQL_ATTR_INPUT_ARRAY_MAXSIZE, |
| rsMaxsize_, |
| NULL); |
| if (retcode != SUCCESS) |
| return retcode; |
| */ |
| |
| retcode = prepare(stmtStr, module_, stmt_, sql_src_, |
| input_desc_, output_desc_, NULL,NULL,NULL,NULL,NULL, |
| NULL,NULL,NULL,monitorThis); |
| if (retcode < 0) |
| { |
| deallocStuff(module_, stmt_, sql_src_, |
| input_desc_, output_desc_); |
| return retcode; |
| } |
| |
| rsInputBuffer_ = new(heap_) char[rsMaxsize_ * inputDatalen_]; |
| |
| retcode = SQL_EXEC_SetDescItem(input_desc_,0,SQLDESC_ROWSET_TYPE, 3, 0); |
| |
| retcode = SQL_EXEC_SetDescItem(input_desc_,0,SQLDESC_ROWWISE_ROWSET_PTR, |
| (long)rsInputBuffer_, 0); |
| |
| retcode = SQL_EXEC_SetDescItem(input_desc_,0,SQLDESC_ROWWISE_ROWSET_ROW_LEN, |
| inputDatalen_, 0); |
| |
| currRSrow_ = 0; |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::rwrsExec( |
| char * inputRow, |
| Int32 inputRowLen, |
| Int64 * rowsAffected) |
| { |
| Lng32 retcode = 0; |
| |
| clearGlobalDiags(); |
| |
| if (rowsAffected) |
| *rowsAffected = 0; |
| |
| if ((inputRow) && (currRSrow_ < rsMaxsize_)) |
| { |
| str_cpy_all(&rsInputBuffer_[currRSrow_ * inputDatalen_], |
| inputRow, inputRowLen); |
| currRSrow_++; |
| return 0; |
| } |
| |
| if ((inputRow == NULL) && (currRSrow_ == 0)) |
| return 0; |
| |
| retcode = SQL_EXEC_SetDescItem(input_desc_, 0, SQLDESC_ROWWISE_ROWSET_SIZE, |
| currRSrow_, 0); |
| |
| retcode = exec(); |
| if (retcode < 0) |
| return retcode; |
| |
| retcode = fetch(); |
| if (retcode < 0) |
| return retcode; |
| |
| Lng32 cliRetcode = -1; |
| if (retcode >= 0) |
| { |
| cliRetcode = retcode; |
| if (rowsAffected) |
| { |
| Lng32 tmpRowsAffected = 0; |
| retcode = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_ROW_COUNT, |
| &tmpRowsAffected, NULL, |
| 0, NULL); |
| |
| if(retcode == EXE_NUMERIC_OVERFLOW) // rowsAffected > LONG_MAX |
| { |
| GetRowsAffected(rowsAffected); |
| } |
| else |
| *rowsAffected = (Int64)tmpRowsAffected; |
| |
| retcode = 0; |
| } |
| } |
| |
| currRSrow_ = 0; |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::rwrsClose() |
| { |
| Lng32 retcode = 0; |
| |
| retcode = rwrsExec(NULL, 0, NULL); |
| |
| close(); |
| |
| deallocStuff(module_, stmt_, sql_src_, |
| input_desc_, output_desc_); |
| |
| return retcode; |
| } |
| |
| short ExeCliInterface::prepareAndExecRowsPrologue(const char * sqlInitialStrBuf, |
| char * sqlSecondaryStrBuf, |
| Queue* initialOutputVarPtrList, |
| Queue* secondaryOutputVarPtrList, |
| Int64 &rowsAffected, |
| NABoolean monitorThis) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| retcode = allocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| // Prepare |
| outputBuf_ = NULL; |
| inputBuf_ = NULL; |
| retcode = prepare(sqlInitialStrBuf, module_, stmt_, sql_src_, |
| input_desc_, output_desc_, &outputBuf_, |
| initialOutputVarPtrList, NULL,NULL,NULL,NULL, |
| NULL,NULL,monitorThis); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| retcode = allocStuff(moduleWithCK_, stmtWithCK_, sql_src_withCK_, |
| input_desc_withCK_, output_desc_withCK_); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| // Prepare |
| outputBuf_withCK_ = NULL; |
| retcode = prepare(sqlSecondaryStrBuf, moduleWithCK_, stmtWithCK_, sql_src_withCK_, |
| input_desc_withCK_, output_desc_withCK_, &outputBuf_withCK_, |
| secondaryOutputVarPtrList,NULL,NULL,NULL,NULL, |
| NULL,NULL,monitorThis); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| // Ensure the input entries have the correct character set type |
| retcode = setCharsetTypes(); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| retcode = SQL_EXEC_Exec(stmt_, input_desc_, 0); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| Lng32 cliRetcode = -1; |
| retcode = SQL_EXEC_Fetch(stmt_, output_desc_, 0); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| if (retcode >= 0) // we continue for warnings (retcode > 0) |
| // and NO errors or warnings (retcode == 0) |
| { |
| cliRetcode = retcode; // save the retcode from cli fetch. |
| setOutputPtrsAsInputPtrs(initialOutputVarPtrList, 0); |
| |
| Int64 tmpRowsAffected = 0; |
| retcode = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_ROW_COUNT, |
| &tmpRowsAffected, NULL, |
| 0, NULL); |
| |
| if(retcode == EXE_NUMERIC_OVERFLOW) // rowsAffected > LONG_MAX |
| { |
| GetRowsAffected(&rowsAffected); |
| } |
| else |
| rowsAffected = tmpRowsAffected; |
| } |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = SQL_EXEC_CloseStmt(stmt_); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| // return the return code from the cli fetch if it succeded. |
| if (cliRetcode != -1) |
| return (short) cliRetcode; |
| else |
| return (short) retcode; |
| } |
| |
| short ExeCliInterface::execContinuingRows(Queue * continuingOutputVarPtrList, |
| Int64 &rowsAffected) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = SQL_EXEC_Exec(stmtWithCK_, input_desc_withCK_, 0); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| Lng32 cliRetcode = -1; |
| retcode = SQL_EXEC_Fetch(stmtWithCK_, output_desc_withCK_, 0); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| if (retcode >= 0) |
| { |
| cliRetcode = retcode; // save the retcode from cli fetch. |
| setOutputPtrsAsInputPtrs(continuingOutputVarPtrList, 0); |
| |
| Int64 tmpRowsAffected = 0; |
| retcode = SQL_EXEC_GetDiagnosticsStmtInfo2(NULL, SQLDIAG_ROW_COUNT, |
| &tmpRowsAffected, NULL, |
| 0, NULL); |
| |
| if(retcode == EXE_NUMERIC_OVERFLOW) // rowsAffected > LONG_MAX |
| { |
| GetRowsAffected(&rowsAffected); |
| } |
| else |
| rowsAffected = tmpRowsAffected; |
| } |
| |
| retcode = SQL_EXEC_CloseStmt(stmtWithCK_); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| // return the return code from the cli fetch if it succeded. |
| if (cliRetcode != -1) |
| return (short) cliRetcode; |
| else |
| return (short) retcode; |
| } |
| |
| Lng32 ExeCliInterface::setCharsetTypes() |
| { |
| Lng32 retcode = 0; |
| Lng32 num_input_entries = 0; |
| |
| // Obtain the number of entries |
| retcode = SQL_EXEC_GetDescEntryCount(input_desc_withCK_, &num_input_entries); |
| |
| if (retcode < 0) |
| return (short)retcode; |
| |
| Lng32 data_charset = 0; |
| |
| for (Lng32 i = 1; i <= num_input_entries; i++) |
| { |
| |
| retcode = SQL_EXEC_GetDescItem(output_desc_withCK_, |
| i, |
| SQLDESC_CHAR_SET, |
| &data_charset, 0, 0, 0, 0); |
| if (retcode < 0) |
| return (short)retcode; |
| |
| if (data_charset != SQLCHARSETCODE_UNKNOWN) |
| { |
| retcode = SQL_EXEC_SetDescItem(input_desc_withCK_, |
| i, |
| SQLDESC_CHAR_SET, |
| data_charset, 0); |
| if (retcode < 0) |
| return (short)retcode; |
| } |
| } |
| |
| return (short)retcode; |
| } |
| |
| void ExeCliInterface::setOutputPtrsAsInputPtrs(Queue* outputVarPtrList, |
| SQLDESC_ID * target_inputDesc) |
| { |
| // Process the queue |
| Int32 j = 1; |
| outputVarPtrList->position(); |
| |
| while (NOT outputVarPtrList->atEnd()) |
| { |
| char * entry = (char*)outputVarPtrList->getCurr(); |
| SQL_EXEC_SetDescItem(input_desc_withCK_, j++, |
| SQLDESC_VAR_PTR, |
| (Long)entry, 0); |
| |
| outputVarPtrList->advance(); |
| } |
| |
| return; |
| } |
| |
| Lng32 ExeCliInterface::prepareAndExecRowsEpilogue() |
| { |
| Lng32 retcode = 0; |
| |
| retcode = close(); |
| |
| deallocStuff(module_, stmt_, sql_src_, input_desc_, output_desc_); |
| |
| if (stmtWithCK_) |
| { |
| retcode = SQL_EXEC_CloseStmt(stmtWithCK_); |
| } |
| |
| deallocStuff(moduleWithCK_, stmtWithCK_, |
| sql_src_withCK_, input_desc_withCK_, output_desc_withCK_); |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::beginWork() |
| { |
| return executeImmediate("begin work;"); |
| } |
| |
| Lng32 ExeCliInterface::commitWork() |
| { |
| return executeImmediate("commit work;"); |
| } |
| |
| Lng32 ExeCliInterface::rollbackWork() |
| { |
| return executeImmediate("rollback work;"); |
| } |
| |
| Lng32 ExeCliInterface::autoCommit(NABoolean v) |
| { |
| if (v) |
| return executeImmediate("set transaction autocommit ON;"); |
| else |
| return executeImmediate("set transaction autocommit OFF;"); |
| } |
| |
| Lng32 ExeCliInterface::beginXn() |
| { |
| return SQL_EXEC_Xact(SQLTRANS_BEGIN, 0); |
| } |
| |
| Lng32 ExeCliInterface::commitXn() |
| { |
| return SQL_EXEC_Xact(SQLTRANS_COMMIT, 0); |
| } |
| |
| Lng32 ExeCliInterface::rollbackXn() |
| { |
| return SQL_EXEC_Xact(SQLTRANS_ROLLBACK, 0); |
| } |
| |
| Lng32 ExeCliInterface::statusXn() |
| { |
| return SQL_EXEC_Xact(SQLTRANS_STATUS, NULL); |
| } |
| |
| Lng32 ExeCliInterface::suspendXn() |
| { |
| return SQL_EXEC_Xact(SQLTRANS_SUSPEND, 0); |
| } |
| |
| Lng32 ExeCliInterface::resumeXn() |
| { |
| return SQL_EXEC_Xact(SQLTRANS_RESUME, 0); |
| } |
| |
| Lng32 ExeCliInterface::createContext(char * contextHandle) |
| { |
| Lng32 rc = 0; |
| rc = SQL_EXEC_CreateContext((SQLCTX_HANDLE*)contextHandle, NULL, FALSE); |
| return rc; |
| } |
| |
| Lng32 ExeCliInterface::switchContext(char * contextHandle) |
| { |
| Lng32 rc = 0; |
| rc = SQL_EXEC_SwitchContext(*(SQLCTX_HANDLE*)contextHandle, NULL); |
| return rc; |
| } |
| |
| Lng32 ExeCliInterface::currentContext(char * contextHandle) |
| { |
| Lng32 rc = 0; |
| rc = SQL_EXEC_CurrentContext((SQLCTX_HANDLE*)contextHandle); |
| return rc; |
| } |
| |
| Lng32 ExeCliInterface::deleteContext(char* contextHandle) // in buf contains context handle |
| { |
| return SQL_EXEC_DeleteContext(*(SQLCTX_HANDLE*)contextHandle); |
| } |
| |
| Lng32 ExeCliInterface::retrieveSQLDiagnostics(ComDiagsArea *toDiags) |
| { |
| Lng32 retcode; |
| ex_assert(toDiags != NULL, "ComDiagsArea is null"); |
| retcode = SQL_EXEC_MergeDiagnostics_Internal(*toDiags); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| return retcode; |
| } |
| |
| |
| ComDiagsArea *ExeCliInterface::allocAndRetrieveSQLDiagnostics(ComDiagsArea *&toDiags) |
| { |
| Lng32 retcode; |
| NABoolean daAllocated = FALSE; |
| if (toDiags == NULL) { |
| toDiags = ComDiagsArea::allocate(heap_); |
| daAllocated = TRUE; |
| } |
| |
| retcode = SQL_EXEC_MergeDiagnostics_Internal(*toDiags); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| if (retcode == 0) |
| return toDiags; |
| else { |
| if (daAllocated) |
| toDiags->decrRefCount(); |
| return NULL; |
| } |
| } |
| |
| Lng32 ExeCliInterface::GetRowsAffected(Int64 *rowsAffected) |
| { |
| SQLDESC_ID *rowCountDesc = NULL; |
| SQLMODULE_ID * module = NULL; |
| |
| Lng32 retcode = SUCCESS; |
| NABoolean sqlWarning = FALSE; |
| |
| SQLDIAG_STMT_INFO_ITEM_ID sqlItem = SQLDIAG_ROW_COUNT; |
| rowCountDesc = new(heap_) SQLDESC_ID; |
| rowCountDesc->version = SQLCLI_CURRENT_VERSION; |
| rowCountDesc->name_mode = desc_handle; |
| module = new(heap_) SQLMODULE_ID; |
| rowCountDesc->module = module; |
| module->module_name = 0; |
| module->charset = "ISO88591"; |
| module->module_name_len = 0; |
| module->version = SQLCLI_CURRENT_VERSION; |
| rowCountDesc->identifier = 0; |
| rowCountDesc->handle = 0; |
| |
| // get number of rows affected |
| |
| retcode = SQL_EXEC_AllocDesc (rowCountDesc, 1); |
| retcode = SQL_EXEC_SetDescItem(rowCountDesc, 1, |
| SQLDESC_TYPE_FS, REC_BIN64_SIGNED, 0); |
| retcode = SQL_EXEC_SetDescItem(rowCountDesc, 1, |
| SQLDESC_VAR_PTR, (Long)rowsAffected, 0); |
| |
| Lng32 *temp; |
| temp = (Lng32 *) &sqlItem; |
| |
| retcode = SQL_EXEC_GetDiagnosticsStmtInfo(temp, rowCountDesc); |
| |
| // free up resources |
| SQL_EXEC_DeallocDesc(rowCountDesc); |
| |
| return SUCCESS; |
| |
| } // GetRowsAffected() |
| |
| Lng32 ExeCliInterface::holdAndSetCQD(const char * defaultName, const char * defaultValue, ComDiagsArea *globalDiags) |
| { |
| Lng32 cliRC; |
| |
| char buf[400]; |
| |
| strcpy(buf, "control query default "); |
| strcat(buf, defaultName); |
| strcat(buf, " hold;"); |
| |
| // hold the current value for defaultName |
| cliRC = executeImmediate(buf, NULL, NULL, TRUE, NULL, 0,&globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| // now set the new value for defaultName |
| strcpy(buf, "control query default "); |
| strcat(buf, defaultName); |
| strcat(buf, " '"); |
| strcat(buf, defaultValue); |
| strcat(buf, "';"); |
| cliRC = executeImmediate(buf, NULL, NULL, TRUE, NULL, 0,&globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| return 0; |
| } |
| |
| |
| Lng32 ExeCliInterface::restoreCQD(const char * defaultName, ComDiagsArea *globalDiags) |
| { |
| Lng32 cliRC; |
| |
| char buf[400]; |
| |
| // remove this cqd from the cqd array |
| strcpy(buf, "control query default "); |
| strcat(buf, defaultName); |
| strcat(buf, " reset;"); |
| cliRC = executeImmediate(buf, NULL, NULL, TRUE, NULL, 0,&globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| // restore the saved cqd default value |
| strcpy(buf, "control query default "); |
| strcat(buf, defaultName); |
| strcat(buf, " restore;"); |
| cliRC = executeImmediate(buf, NULL, NULL, TRUE, NULL, 0,&globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::getCQDval(const char * defaultName, |
| char * val, |
| ComDiagsArea *globalDiags) |
| |
| { |
| Lng32 cliRC; |
| |
| char buf[400]; |
| |
| strcpy(buf, "cqd showcontrol_show_all 'ON';"); |
| cliRC = executeImmediate(buf); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| char valBuf[4000]; |
| Lng32 valBufLen = 0; |
| strcpy(buf, "showcontrol default "); |
| strcat(buf, defaultName); |
| strcat(buf, ", match full, no header;"); |
| |
| cliRC = executeImmediate(buf, valBuf, &valBufLen); |
| if (cliRC < 0) |
| { |
| strcpy(buf, "cqd showcontrol_show_all 'OFF';"); |
| executeImmediate(buf); |
| |
| return cliRC; |
| } |
| |
| strcpy(val, valBuf); |
| |
| strcpy(buf, "cqd showcontrol_show_all 'OFF';"); |
| cliRC = executeImmediate(buf); |
| |
| return 0; |
| } |
| |
| Lng32 ExeCliInterface::setCQS(const char * shape, ComDiagsArea *globalDiags) |
| { |
| Lng32 cliRC; |
| |
| cliRC = executeImmediate(shape, NULL, NULL, TRUE, NULL, 0,&globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| return 0; |
| } |
| |
| |
| Lng32 ExeCliInterface::resetCQS(ComDiagsArea * globalDiags) |
| { |
| Lng32 cliRC; |
| |
| char buf[400]; |
| |
| strcpy(buf, "control query shape cut "); |
| cliRC = executeImmediate(buf, NULL, NULL, TRUE, NULL, 0,&globalDiags); |
| if (cliRC < 0) |
| { |
| return cliRC; |
| } |
| |
| return 0; |
| } |
| |
| |
| // methods for routine invocation |
| |
| Lng32 ExeCliInterface::getRoutine( |
| /* IN */ const char *serializedInvocationInfo, |
| /* IN */ Int32 invocationInfoLen, |
| /* IN */ const char *serializedPlanInfo, |
| /* IN */ Int32 planInfoLen, |
| /* IN */ Int32 language, |
| /* IN */ Int32 paramStyle, |
| /* IN */ const char *externalName, |
| /* IN */ const char *containerName, |
| /* IN */ const char *externalPath, |
| /* IN */ const char *librarySqlName, |
| /* OUT */ Int32 *handle, |
| /* IN/OUT */ ComDiagsArea *diags) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = SQL_EXEC_GetRoutine( |
| serializedInvocationInfo, |
| invocationInfoLen, |
| serializedPlanInfo, |
| planInfoLen, |
| language, |
| paramStyle, |
| externalName, |
| containerName, |
| externalPath, |
| librarySqlName, |
| handle); |
| |
| if (retcode != 0 && diags) |
| { |
| SQL_EXEC_MergeDiagnostics_Internal(*diags); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| } |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::invokeRoutine( |
| /* IN */ Int32 handle, |
| /* IN */ Int32 phaseEnumAsInt, |
| /* IN */ const char *serializedInvocationInfo, |
| /* IN */ Int32 invocationInfoLen, |
| /* OUT */ Int32 *invocationInfoLenOut, |
| /* IN */ const char *serializedPlanInfo, |
| /* IN */ Int32 planInfoLen, |
| /* IN */ Int32 planNum, |
| /* OUT */ Int32 *planInfoLenOut, |
| /* IN */ char *inputRow, |
| /* IN */ Int32 inputRowLen, |
| /* OUT */ char *outputRow, |
| /* IN */ Int32 outputRowLen, |
| /* IN/OUT */ ComDiagsArea *diags) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = SQL_EXEC_InvokeRoutine( |
| handle, |
| phaseEnumAsInt, |
| serializedInvocationInfo, |
| invocationInfoLen, |
| invocationInfoLenOut, |
| serializedPlanInfo, |
| planInfoLen, |
| planNum, |
| planInfoLenOut, |
| inputRow, |
| inputRowLen, |
| outputRow, |
| outputRowLen); |
| |
| if (retcode != 0 && diags) |
| { |
| SQL_EXEC_MergeDiagnostics_Internal(*diags); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| } |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::getRoutineInvocationInfo( |
| /* IN */ Int32 handle, |
| /* IN/OUT */ char *serializedInvocationInfo, |
| /* IN */ Int32 invocationInfoMaxLen, |
| /* OUT */ Int32 *invocationInfoLenOut, |
| /* IN/OUT */ char *serializedPlanInfo, |
| /* IN */ Int32 planInfoMaxLen, |
| /* IN */ Int32 planNum, |
| /* OUT */ Int32 *planInfoLenOut, |
| /* IN/OUT */ ComDiagsArea *diags) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = SQL_EXEC_GetRoutineInvocationInfo( |
| handle, |
| serializedInvocationInfo, |
| invocationInfoMaxLen, |
| invocationInfoLenOut, |
| serializedPlanInfo, |
| planInfoMaxLen, |
| planNum, |
| planInfoLenOut); |
| |
| if (retcode != 0 && diags) |
| { |
| SQL_EXEC_MergeDiagnostics_Internal(*diags); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| } |
| |
| return retcode; |
| } |
| |
| Lng32 ExeCliInterface::putRoutine( |
| /* IN */ Int32 handle, |
| /* IN/OUT */ ComDiagsArea *diags) |
| { |
| Lng32 retcode = 0; |
| |
| SQL_EXEC_ClearDiagnostics(NULL); |
| |
| retcode = SQL_EXEC_PutRoutine( |
| handle); |
| |
| if (retcode != 0 && diags) |
| { |
| SQL_EXEC_MergeDiagnostics_Internal(*diags); |
| SQL_EXEC_ClearDiagnostics(NULL); |
| } |
| |
| return retcode; |
| } |