blob: fa0f3d16e3a78a2da15f7bd3a839ec50cdd068d7 [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: SqlciCmd.C
* Description:
*
* Created: 4/15/95
* Language: C++
*
*
*
*
*****************************************************************************
*/
#include <errno.h>
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <stdlib.h>
#include <wchar.h>
#include "Platform.h"
#include "NAWinNT.h"
#include "ComCextdecs.h"
#include "ComDiags.h"
#include "ComSmallDefs.h"
#include "ErrorMessage.h"
#include "GetErrorMessage.h"
#include "InputStmt.h"
#include "SqlciError.h"
#include "SqlciCmd.h"
#include "sqlcmd.h"
#include "ShellCmd.h"
#include "SqlciError.h"
#include "SqlciParser.h"
#include "str.h"
#include "charinfo.h"
#include "SqlciEnv.h"
#include "Sqlci.h"
#include "sql_id.h"
#include "ComRtUtils.h"
#include "ComUser.h"
extern ComDiagsArea sqlci_DA;
SqlciCmd::SqlciCmd(const sqlci_cmd_type cmd_type_)
: SqlciNode(SqlciNode::SQLCI_CMD_TYPE),
cmd_type(cmd_type_)
{
arglen = 0;
argument = 0;
}
SqlciCmd::SqlciCmd(const sqlci_cmd_type cmd_type_, char * argument_, Lng32 arglen_)
: SqlciNode(SqlciNode::SQLCI_CMD_TYPE),
cmd_type(cmd_type_)
{
arglen = arglen_;
if (argument_)
{
argument = new char[arglen_ + 1];
strncpy(argument, argument_,arglen_);
argument[arglen] = 0;
}
else
{
argument = 0;
}
};
SqlciCmd::SqlciCmd(const sqlci_cmd_type cmd_type_, NAWchar * argument_, Lng32 arglen_)
: SqlciNode(SqlciNode::SQLCI_CMD_TYPE),
cmd_type(cmd_type_)
{
arglen = 2*arglen_;
if (argument_)
{
NAWchar* tgt = new NAWchar[arglen_ + 1]; // extra byte for NAWchar typed argument
NAWstrncpy(tgt, argument_,arglen_);
tgt[arglen_] = 0;
argument = (char*) tgt;
}
else
{
argument = 0;
}
};
SqlciCmd::SqlciCmd(const sqlci_cmd_type cmd_type_, Int32 argument_)
: SqlciNode(SqlciNode::SQLCI_CMD_TYPE),
cmd_type(cmd_type_)
{
numeric_arg = argument_;
argument = 0;
};
SqlciCmd::~SqlciCmd()
{
delete [] argument;
};
FixCommand::FixCommand(char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::FC_TYPE, argument_, arglen_)
{
cmd = argument_;
};
FixCommand::FixCommand(Int32 argument_, short neg_num_)
: SqlciCmd(SqlciCmd::FC_TYPE, argument_)
{
cmd_num = argument_;
neg_num = neg_num_;
cmd = 0;
};
Obey::Obey(char * argument_, Lng32 arglen_, char * section_name_)
: SqlciCmd(SqlciCmd::OBEY_TYPE, argument_, arglen_)
{
if (section_name_)
{
section_name = new char[strlen(section_name_)+1];
strcpy (section_name, section_name_);
}
else
{
section_name = 0;
}
};
Log::Log(char * argument_, Lng32 arglen_, log_type type_, Int32 commands_only)
: SqlciCmd(SqlciCmd::LOG_TYPE, argument_, arglen_),
type(type_), commandsOnly_(commands_only)
{
};
Shape::Shape(NABoolean type, char * infile, char * outfile)
: SqlciCmd(SqlciCmd::SHAPE_TYPE),
type_(type), infile_(infile), outfile_(outfile)
{
};
Statistics::Statistics(char * argument_, Lng32 arglen_,StatsCmdType type,
char * statsOptions)
: SqlciCmd(SqlciCmd::STATISTICS_TYPE, argument_, arglen_),
type_(type)
{
if (statsOptions)
{
statsOptions_ = new char[strlen(statsOptions)+1];
strcpy (statsOptions_, statsOptions);
}
else
{
statsOptions_ = NULL;
}
};
Statistics::~Statistics()
{
if (statsOptions_)
delete [] statsOptions_;
};
QueryId::QueryId(char * argument_, Lng32 arglen_,
NABoolean isSet, char * qidVal)
: SqlciCmd(SqlciCmd::QUERYID_TYPE, argument_, arglen_),
isSet_(isSet), qidVal_(NULL)
{
if ((isSet_) && (qidVal))
{
qidVal_ = new char[strlen(qidVal) + 1];
strcpy(qidVal_, qidVal);
}
};
QueryId::~QueryId()
{
if (qidVal_)
delete qidVal_;
}
History::History(char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::HISTORY_TYPE, argument_, arglen_)
{
};
ListCount::ListCount(char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::LISTCOUNT_TYPE, argument_, arglen_)
{
};
Mode::Mode(ModeType type_, NABoolean value)
: SqlciCmd(SqlciCmd::MODE_TYPE),
value(value)
{
type = type_;
};
Verbose::Verbose(char * argument_, Lng32 arglen_, VerboseCmdType type)
: SqlciCmd(SqlciCmd::VERBOSE_TYPE, argument_, arglen_),
type_(type)
{
};
ParserFlags::ParserFlags(ParserFlagsOperation opType_, Int32 param_)
: SqlciCmd(SqlciCmd::PARSERFLAGS_TYPE, param_)
{
opType = opType_;
param = param_;
};
Error::Error(char * argument_, Lng32 arglen_, error_type type_)
: SqlciCmd(SqlciCmd::ERROR_TYPE, argument_, arglen_)
{
type = type_;
};
FCRepeat::FCRepeat(char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::REPEAT_TYPE, argument_, arglen_)
{
cmd = argument_;
};
FCRepeat::FCRepeat(Int32 argument_, short neg_num_)
: SqlciCmd(SqlciCmd::REPEAT_TYPE, argument_)
{
cmd_num = argument_;
neg_num = neg_num_;
cmd = 0;
};
Exit::Exit(char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::EXIT_TYPE, argument_, arglen_)
{
};
Reset::Reset(reset_type type_, char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::SETPARAM_TYPE, argument_, arglen_),
type(type_)
{
};
Reset::Reset(reset_type type_)
: SqlciCmd(SqlciCmd::SETPARAM_TYPE),
type(type_)
{
};
SetParam::SetParam(char * param_name_, Lng32 namelen_, char * argument_, Lng32 arglen_, CharInfo::CharSet x)
: SqlciCmd(SqlciCmd::SETPARAM_TYPE, argument_, arglen_),
cs(x), inSingleByteForm_(TRUE),
m_convUTF16ParamStrLit(NULL),
isQuotedStrWithoutCharSetPrefix_(FALSE),
m_termCS(CharInfo::UnknownCharSet)
{
if (param_name_)
{
param_name = new char[namelen_+1];
strcpy (param_name, param_name_);
namelen = namelen_;
}
else
{
param_name = 0;
namelen = 0;
}
};
SetParam::SetParam(char * param_name_, Lng32 namelen_, NAWchar * argument_, Lng32 arglen_, CharInfo::CharSet x)
: SqlciCmd(SqlciCmd::SETPARAM_TYPE, argument_, arglen_),
cs(x), inSingleByteForm_(FALSE),
m_convUTF16ParamStrLit(NULL),
isQuotedStrWithoutCharSetPrefix_(FALSE),
m_termCS(CharInfo::UnknownCharSet)
{
if (param_name_)
{
param_name = new char[namelen_+1];
strcpy (param_name, param_name_);
namelen = namelen_;
}
else
{
param_name = 0;
namelen = 0;
}
};
SetPattern::SetPattern(char * pattern_name_, Lng32 namelen_, char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::SETPATTERN_TYPE, argument_, arglen_)
{
if (pattern_name_)
{
pattern_name = new char[namelen_+1];
strcpy (pattern_name, pattern_name_);
namelen = namelen_;
}
else
{
pattern_name = 0;
namelen = 0;
}
};
short SetTerminalCharset::process(SqlciEnv * sqlci_env)
{
HandleCLIErrorInit();
char* tcs = get_argument();
Int32 tcs_len;
if ( tcs != NULL && ((tcs_len=strlen(tcs)) <= 128) )
{
char tcs_uppercase[129];
str_cpy_convert(tcs_uppercase, tcs, tcs_len, 1);
tcs_uppercase[tcs_len] = 0;
if ( CharInfo::isCharSetSupported(tcs_uppercase) == FALSE )
{
SqlciError (SQLCI_INVALID_TERMINAL_CHARSET_NAME_ERROR,
(ErrorParam *) 0
);
return 0;
}
if ( CharInfo::isTerminalCharSetSupported(tcs_uppercase) == FALSE )
{
ErrorParam *ep = new ErrorParam(tcs);
SqlciError (2038,
ep,
(ErrorParam *) 0
);
delete ep;
return 0;
}
// The following code had been commented out but has been restored
// for the charset project CQD removed on 12/11/2007
/*
char cqd_stmt[200]; // charset name can be up to 128 bytes long
sprintf(cqd_stmt, "CONTROL QUERY DEFAULT TERMINAL_CHARSET '%s';",
tcs_uppercase
);
long retcode = SqlCmd::executeQuery(cqd_stmt, sqlci_env);
if ( retcode == 0 )*/
sqlci_env -> setTerminalCharset(
CharInfo::getCharSetEnum(tcs_uppercase)
);
// else
// HandleCLIError(retcode, sqlci_env);
} else
SqlciError (SQLCI_INVALID_TERMINAL_CHARSET_NAME_ERROR,
(ErrorParam *) 0
);
return 0;
}
short SetIsoMapping::process(SqlciEnv * sqlci_env)
{
HandleCLIErrorInit();
char* omcs = get_argument();
Int32 omcs_len;
if ( omcs != NULL && ((omcs_len=strlen(omcs)) <= 128) )
{
char omcs_uppercase[129];
str_cpy_convert(omcs_uppercase, omcs, omcs_len, 1);
omcs_uppercase[omcs_len] = 0;
if ( strcmp(omcs_uppercase, "ISO88591") != 0
)
{
// 15001 42000 99999 BEGINNER MAJOR DBADMIN
// A syntax error occurred at or before: $0~string0
ErrorParam *ep = new ErrorParam(omcs);
SqlciError (15001,
ep,
(ErrorParam *) 0
);
delete ep;
return 0;
}
} else {
// 15001 42000 99999 BEGINNER MAJOR DBADMIN
// A syntax error occurred at or before: $0~string0
ErrorParam *ep;
if (omcs)
ep = new ErrorParam(omcs);
else
ep = new ErrorParam("ISO_MAPPING");
SqlciError (15001,
ep,
(ErrorParam *) 0
);
delete ep;
}
return 0;
}
short SetDefaultCharset::process(SqlciEnv * sqlci_env)
{
HandleCLIErrorInit();
char* dcs = get_argument();
Int32 dcs_len;
if ( dcs != NULL && ((dcs_len=strlen(dcs)) <= 128) )
{
char dcs_uppercase[129];
str_cpy_convert(dcs_uppercase, dcs, dcs_len, 1);
dcs_uppercase[dcs_len] = 0;
if ( strcmp(dcs_uppercase, "ISO88591") != 0 &&
strcmp(dcs_uppercase, "UTF8" ) != 0 &&
strcmp(dcs_uppercase, "SJIS" ) != 0
)
{
// 15001 42000 99999 BEGINNER MAJOR DBADMIN
// A syntax error occurred at or before: $0~string0
ErrorParam *ep = new ErrorParam(dcs);
SqlciError (15001,
ep,
(ErrorParam *) 0
);
delete ep;
return 0;
}
char cqd_stmt[200]; // charset name can be up to 128 bytes long
sprintf(cqd_stmt, "CONTROL QUERY DEFAULT DEFAULT_CHARSET '%s';",
dcs_uppercase
);
Lng32 retcode = SqlCmd::executeQuery(cqd_stmt, sqlci_env);
if ( retcode == 0 )
sqlci_env -> setDefaultCharset(CharInfo::getCharSetEnum(dcs_uppercase));
else
HandleCLIError(retcode, sqlci_env);
} else {
// 15001 42000 99999 BEGINNER MAJOR DBADMIN
// A syntax error occurred at or before: $0~string0
ErrorParam *ep;
if (dcs)
ep = new ErrorParam(dcs);
else
ep = new ErrorParam("DEFAULT_CHARSET");
SqlciError (15001,
ep,
(ErrorParam *) 0
);
delete ep;
}
return 0;
}
short SetInferCharset::process(SqlciEnv * sqlci_env)
{
HandleCLIErrorInit();
char* ics = get_argument();
Int32 ics_len;
if ( ics != NULL && ((ics_len=strlen(ics)) <= 128) )
{
char ics_uppercase[129];
str_cpy_convert(ics_uppercase, ics, ics_len, 1);
ics_uppercase[ics_len] = 0;
if ( strcmp(ics_uppercase, "FALSE") != 0 &&
strcmp(ics_uppercase, "TRUE" ) != 0 &&
strcmp(ics_uppercase, "0" ) != 0 &&
strcmp(ics_uppercase, "1" ) != 0 )
{
// 15001 42000 99999 BEGINNER MAJOR DBADMIN
// A syntax error occurred at or before: $0~string0
ErrorParam *ep = new ErrorParam(ics);
SqlciError (15001,
ep,
(ErrorParam *) 0
);
delete ep;
return 0;
}
char cqd_stmt[200]; // charset name can be up to 128 bytes long
sprintf(cqd_stmt, "CONTROL QUERY DEFAULT INFER_CHARSET '%s';",
ics_uppercase
);
Lng32 retcode = SqlCmd::executeQuery(cqd_stmt, sqlci_env);
if ( retcode == 0 )
{
if ( ics_uppercase[0] == '1' || ics_uppercase[0] == 'T'/*RUE*/)
sqlci_env -> setInferCharset(TRUE);
else
sqlci_env -> setInferCharset(FALSE);
}
else
HandleCLIError(retcode, sqlci_env);
} else {
// 15001 42000 99999 BEGINNER MAJOR DBADMIN
// A syntax error occurred at or before: $0~string0
ErrorParam *ep;
if (ics)
ep = new ErrorParam(ics);
else
ep = new ErrorParam("INFER_CHARSET");
SqlciError (15001,
ep,
(ErrorParam *) 0
);
delete ep;
}
return 0;
}
Show::Show(show_type type_, NABoolean allValues)
: SqlciCmd(SqlciCmd::SHOW_TYPE),
allValues_(allValues)
{
type = type_;
};
Wait::Wait(char * argument_, Lng32 arglen_)
: SqlciCmd(SqlciCmd::WAIT_TYPE, argument_, arglen_)
{
};
//////////////////////////////////////////////////
short Exit::process(SqlciEnv * sqlci_env)
{
// Default is to exit sqlci. In the special case of an
// active transaction, the user may choose not to exit.
short retval = -1;
if (sqlci_env->statusTransaction())
{
// ## The following English text needs to come from the message file
// ## so it can be translated, for I18N:
sqlci_env->get_logfile()->WriteAll("\nThere is an active transaction. Do you want to commit the transaction?");
sqlci_env->get_logfile()->WriteAll(" Y to commit transaction");
sqlci_env->get_logfile()->WriteAll(" N to abort transaction");
sqlci_env->get_logfile()->WriteAllWithoutEOL(" Any other key to resume in MXCI: ");
char response[2];
response[0] = 'N'; // noninteractive default
response[1] = '\0'; // terminate string for WriteAll
if (sqlci_env->isInteractiveSession())
{
cin.clear(); clearerr(stdin);
cin.get(response[0]);
if (cin.eof())
{
// EOF encountered. Treat this as any key other than [YyNn]
response[0] = '\0';
// Output a '\n' since EOF keeps the cursor on the same line
cout << endl;
cin.clear(); clearerr(stdin);
}
}
// If not EOF and not simple ENTER/RETURN, then
// display the character; if furthermore we're interactive, then
// throw away the rest of the input line.
if (response[0] == '\n')
sqlci_env->get_logfile()->WriteAll("", 0); // write ONE endl, not 2
else if (response[0])
{
sqlci_env->get_logfile()->WriteAll(response, 1);
if (sqlci_env->isInteractiveSession())
{
InputStmt ignore(sqlci_env);
ignore.consumeLine();
}
}
// What if the executeQuery's below fail? should we still emit the
// WriteAll "Transaction XXXed" message and proceed to exit?
switch (response[0])
{
case 'y':
case 'Y':
SqlCmd::executeQuery("COMMIT WORK;", sqlci_env);
sqlci_env->get_logfile()->WriteAll("Transaction committed."); //##I18N
retval = -1;
break;
case 'n':
case 'N':
SqlCmd::executeQuery("ROLLBACK WORK;", sqlci_env);
sqlci_env->get_logfile()->WriteAll("Transaction aborted."); // ##I18N
retval = -1;
break;
default:
sqlci_env->get_logfile()->WriteAll("Transaction state maintained."); // ##I18N
retval = 0;
break;
}
} // if transaction is active
// tell CLI that this user session is finished.
SqlCmd::executeQuery("SET SESSION DEFAULT SQL_SESSION 'DROP';", sqlci_env);
if (retval == -1)
{
sqlci_env->get_logfile()->WriteAll("\nEnd of MXCI Session\n"); // ##I18N
}
return retval;
}
//////////////////////////////////////////////
// Begin ERROR
////////////////////////////////////////////////
short Error::process(SqlciEnv * sqlci_env)
{
NAWchar *error_msg;
Int32 codeE, codeW;
char stateE[10], stateW[10];
NABoolean msgNotFound;
ostringstream omsg;
#define GETERRORMESS(in, out, typ) GetErrorMessage(in, (NAWchar *&)out, typ)
codeW = ABS(atoi(get_argument())); // >= 0, i.e. warning
codeE = -codeW; // <= 0, i.e. error
// These calls must be done before any of the GETERRORMESS(),
// as they all use (overwrite) the same static buffer in GetErrorMessage.cpp.
ComSQLSTATE(codeE, stateE);
ComSQLSTATE(codeW, stateW);
msgNotFound = GETERRORMESS(codeE, error_msg, ERROR_TEXT);
if (type == ENVCMD_)
{
if (msgNotFound)
{
error_msg[0] = NAWchar('\n');
error_msg[1] = NAWchar('\0');
}
else
{
// Extract the {braces-enclosed version string}
// that msgfileVrsn.ksh (called by GenErrComp.bat)
// has put into this ENVCMD_ message.
NAWchar *v = NAWstrchr(error_msg, NAWchar(']'));
if (v) error_msg = v;
v = NAWstrchr(error_msg, NAWchar('{'));
if (v) error_msg = v;
v = NAWstrchr(error_msg, NAWchar('}'));
if (v++ && *v == NAWchar('.')) *v = NAWchar(' ');
}
NAWriteConsole(error_msg, omsg, FALSE);
}
else if (!msgNotFound || codeE == 0) // SQL "success", special case
{
omsg << "\n*** SQLSTATE (Err): " << stateE
<< " SQLSTATE (Warn): " << stateW;
omsg << endl;
NAWriteConsole(error_msg,omsg, TRUE);
}
else
{
// Msg not found.
ComDiagsArea diags;
diags << DgSqlCode(codeW);
NADumpDiags(omsg, &diags, TRUE/*newline*/);
}
#if 0 // CAUSE/EFFECT/RECOVERY text not implemented yet!
if (!msgNotFound && type == DETAIL_)
{
GETERRORMESS(codeE, error_msg, CAUSE_TEXT);
NAWriteConsole(error_msg,omsg, TRUE);
GETERRORMESS(codeE, error_msg, EFFECT_TEXT);
NAWriteConsole(error_msg,omsg, TRUE);
GETERRORMESS(codeE, error_msg, RECOVERY_TEXT);
NAWriteConsole(error_msg,omsg, TRUE);
}
#endif // 0 // CAUSE/EFFECT/RECOVERY text not implemented yet!
omsg << ends; // to tack on a null-terminator
sqlci_env->get_logfile()->WriteAllWithoutEOL(omsg.str().c_str());
return 0;
}
//////////////////////////////////////////////////
// Begin SHAPE
///////////////////////////////////////////////////
short Shape::process(SqlciEnv * sqlci_env)
{
sqlci_env->showShape() = type_;
if (! infile_)
return 0;
// open the infile to read Sql statements from
FILE * fStream = 0;
fStream = fopen(infile_, "r");
if (!fStream)
{
ErrorParam *p1 = new ErrorParam (errno);
ErrorParam *p2 = new ErrorParam (infile_);
SqlciError (SQLCI_OBEY_FOPEN_ERROR,
p1,
p2,
(ErrorParam *) 0
);
delete p1;
delete p2;
return 0;
}
// close and remember the current logfile
char * logname = NULL;
if (sqlci_env->get_logfile()->IsOpen())
{
logname = new char[strlen(sqlci_env->get_logfile()->Logname()) + 1];
strcpy(logname, sqlci_env->get_logfile()->Logname());
sqlci_env->get_logfile()->Close();
}
// if infile is the same as outfile, generate output into a temp
// file(called outfile_ + __temp), and then rename it to infile.
// Also, rename infile to infile.bak.
NABoolean tempFile = FALSE;
char * tempOutfile = NULL;
if (outfile_)
{
if (strcmp(infile_, outfile_) == 0)
{
tempFile = TRUE;
tempOutfile = new char[strlen(outfile_) +
strlen("__temp") + 1];
strcpy(tempOutfile, outfile_);
strcat(tempOutfile, "__temp");
}
else
tempOutfile = outfile_;
sqlci_env->get_logfile()->Open(tempOutfile, Logfile::CLEAR_);
}
////////////////////////////////////////////////////////////////
// BEGIN PROCESS NEXT INPUT STMT
////////////////////////////////////////////////////////////////
short retcode = processNextStmt(sqlci_env, fStream);
if (retcode)
{
if(logname != NULL)
delete [] logname;
return retcode;
}
////////////////////////////////////////////////////////////////
// END PROCESS NEXT INPUT STMT
////////////////////////////////////////////////////////////////
fclose(fStream);
if (outfile_)
{
sqlci_env->get_logfile()->Close();
char buf[200];
if (tempFile)
{
snprintf(buf, 200, "sh mv %s %s.bak", infile_, infile_);
ShellCmd * shCmd = new Shell(buf);
shCmd->process(sqlci_env);
delete shCmd;
snprintf(buf, 200, "sh mv %s %s", tempOutfile, infile_);
shCmd = new Shell(buf);
shCmd->process(sqlci_env);
delete shCmd;
}
}
// reopen the original logfile
if (logname)
sqlci_env->get_logfile()->Open(logname, Logfile::APPEND_);
delete [] logname;
delete [] tempOutfile;
tempOutfile = NULL;
return 0;
}
short Shape::processNextStmt(SqlciEnv * sqlci_env, FILE * fStream)
{
short retcode = 0;
enum ShapeState
{
PROCESS_STMT, DONE
};
Int32 done = 0;
Int32 ignore_toggle = 0;
ShapeState state;
InputStmt * input_stmt;
SqlciNode * sqlci_node = NULL;
state = PROCESS_STMT;
while (!done)
{
input_stmt = new InputStmt(sqlci_env);
Int32 read_error = 0;
if (state != DONE)
{
read_error = input_stmt->readStmt(fStream, TRUE);
if (feof(fStream) || read_error == -99)
{
if (!input_stmt->isEmpty() && read_error != -4)
{
// Unterminated statement in obey file.
// Make the parser emit an error message.
input_stmt->display((UInt16)0, TRUE);
input_stmt->logStmt(TRUE);
input_stmt->syntaxErrorOnEof();
}
state = DONE;
} // feof or error (=-99)
}
// if there is an eof directly after a statement
// that is terminated with a semi-colon, process the
// statement
if (read_error == -4) state = PROCESS_STMT;
switch (state)
{
case PROCESS_STMT:
{
Int32 ignore_stmt = input_stmt->isIgnoreStmt();
if (ignore_stmt)
ignore_toggle = ~ignore_toggle;
if (ignore_stmt || ignore_toggle || input_stmt->ignoreJustThis())
{
// ignore until stmt following the untoggling ?ignore
sqlci_DA.clear();
}
else
{
if (!read_error || read_error == -4)
{
sqlci_parser(input_stmt->getPackedString(),
input_stmt->getPackedString(),
&sqlci_node,sqlci_env);
if ((sqlci_node) &&
(sqlci_node->getType() == SqlciNode::SQL_CMD_TYPE))
{
delete sqlci_node;
SqlCmd sqlCmd(SqlCmd::DML_TYPE, NULL);
short retcode = sqlCmd.showShape(sqlci_env,
input_stmt->getPackedString());
if (retcode)
{
delete input_stmt;
return retcode;
}
}
input_stmt->display((UInt16)0, TRUE);
input_stmt->logStmt(TRUE);
}
sqlci_env->displayDiagnostics() ;
// Clear the DiagnosticsArea for the next command...
sqlci_DA.clear();
// if an EXIT statement was seen, then a -1 will be returned
// from process. We are done in that case.
if (retcode == -1)
state = DONE;
}
}
break;
case DONE:
{
done = -1;
}
break;
default:
{
}
break;
} // switch on state
delete input_stmt;
} // while not done
return 0;
}
//////////////////////////////////////////////////
short Wait::process(SqlciEnv * sqlci_env)
{
char buf[100];
cout << "Enter a character + RETURN to continue: ";
cin >> buf;
return 0;
}
//////////////////////////////////////////////////
short ParserFlags::process(SqlciEnv * sqlci_env)
{
Int32 retCode;
if (!ComUser::isRootUserID())
{
// Return - "not authorized" error
ComDiagsArea diags;
diags << DgSqlCode(-1017);
handleLocalError(&diags, sqlci_env);
return -1;
}
if (opType == DO_SET)
{
if (param == 0)
{
// Warning 3190:
// Please use "RESET PARSERFLAGS <value>" to reset the flags.
ComDiagsArea diags;
diags << DgSqlCode(3190);
handleLocalError(&diags, sqlci_env);
}
retCode = SQL_EXEC_SetParserFlagsForExSqlComp_Internal2(param);
}
else
{
// It's DO_RESET
retCode = SQL_EXEC_ResetParserFlagsForExSqlComp_Internal2(param);
}
if (retCode)
{
// This is most probably error 1017:
// You are not authorized to perform this operation.
ComDiagsArea diags;
diags << DgSqlCode(retCode);
handleLocalError(&diags, sqlci_env);
}
return 0;
}
///////////////////////////////
//Process of the MODE Command//
///////////////////////////////
// SQL is the normal mode in which MXCI executes.
short Mode::process(SqlciEnv * sqlci_env)
{
short retcode = 1;
switch (type)
{
case SQL_:
retcode = process_sql(sqlci_env);
break;
default:
SqlciError(SQLCI_INVALID_MODE
,(ErrorParam *) 0 );
break;
}
return retcode;
}
short Mode::process_sql(SqlciEnv * sqlci_env)
{
if (SqlciEnv::SQL_ == sqlci_env->getMode())
{
SqlciError(SQLCI_RW_MODE_ALREADY_SQL
,(ErrorParam *) 0 );
return 0;
}
sqlci_env->setMode(SqlciEnv::SQL_);
return 0;
}
short QueryId::process(SqlciEnv * sqlci_env)
{
Lng32 retcode = 0;
HandleCLIErrorInit();
char * stmtName = get_argument();
PrepStmt * prep_stmt = NULL;
if ((stmtName) &&
(! (prep_stmt = sqlci_env->get_prep_stmts()->get(stmtName))))
{
sqlci_env->diagsArea() << DgSqlCode(-SQLCI_STMT_NOT_FOUND)
<< DgString0(stmtName);
return 0;
}
Logfile *log = sqlci_env->get_logfile();
char sprintfBuf[225];
if (!stmtName)
{
//try to find the last executed statement if present
if (sqlci_env->lastExecutedStmt() && sqlci_env->lastExecutedStmt()->getStmtNameLen() > 0)
stmtName = sqlci_env->lastExecutedStmt()->getStmtName();
//if not, try to find the last prepared statement if present
else if (sqlci_env->getLastAllocatedStmt() && sqlci_env->getLastAllocatedStmt()->identifier_len > 0)
stmtName = (char *) sqlci_env->getLastAllocatedStmt()->identifier;
}
if (!stmtName)
// no statement name found Display error.
{
sprintf(sprintfBuf, "No statement found. Enter command with valid statement name.");
log->WriteAll(sprintfBuf);
return 0;
}
SQLSTMT_ID stmt;
SQLMODULE_ID module;
init_SQLMODULE_ID(&module);
init_SQLSTMT_ID(&stmt, SQLCLI_CURRENT_VERSION,
stmt_name, &module);
char * id = new char[strlen(stmtName) + 1];
stmt.identifier_len = strlen(stmtName);
str_cpy_all(id,stmtName,
stmt.identifier_len);
id[stmt.identifier_len] = 0;
stmt.identifier = id;
char queryId[200];
Lng32 queryIdLen;
if (isSet_)
{
// change query id in prep_stmt
if (prep_stmt->uniqueQueryId())
{
delete prep_stmt->uniqueQueryId();
prep_stmt->uniqueQueryIdLen() = 0;
}
prep_stmt->uniqueQueryIdLen() = strlen(qidVal_);
prep_stmt->uniqueQueryId() = new char[prep_stmt->uniqueQueryIdLen() + 1];
strcpy(prep_stmt->uniqueQueryId(), qidVal_);
retcode = SQL_EXEC_SetStmtAttr(&stmt, SQL_ATTR_UNIQUE_STMT_ID,
0, qidVal_);
delete [] id;
log->WriteAll("");
return 0;
}
retcode = SQL_EXEC_GetStmtAttr(&stmt, SQL_ATTR_UNIQUE_STMT_ID,
NULL, queryId, 200, &queryIdLen);
delete [] id;
if (queryIdLen < 200)
queryId[queryIdLen] = 0;
else
queryId[199] = 0;
HandleCLIError(retcode, sqlci_env);
if (retcode == 0)
{
snprintf(sprintfBuf, 225, "QID is %s",queryId);
log->WriteAll(sprintfBuf);
log->WriteAll("");
}
// display details of this query
// for string attributes, use {type,maxLength,char[maxLength+1]}
UNIQUEQUERYID_ATTR queryIdAttrs[11] =
{
{UNIQUEQUERYID_SEGMENTNUM, 0, 0},
{UNIQUEQUERYID_SEGMENTNAME, 10, new char[11]},
{UNIQUEQUERYID_CPU, 0, 0},
{UNIQUEQUERYID_PIN, 0, 0},
{UNIQUEQUERYID_EXESTARTTIME, 0, 0},
{UNIQUEQUERYID_SESSIONNUM, 0, 0},
{UNIQUEQUERYID_USERNAME, 24, new char[25]},
{UNIQUEQUERYID_SESSIONNAME, 32, new char[33]},
{UNIQUEQUERYID_QUERYNUM, 0, 0},
{UNIQUEQUERYID_STMTNAME, 110, new char[111]},
{UNIQUEQUERYID_SESSIONID, 104, new char[105]}
};
retcode = SQL_EXEC_GetUniqueQueryIdAttrs(queryId, queryIdLen,
11, queryIdAttrs);
HandleCLIError(retcode, sqlci_env);
if (retcode == 0)
{
snprintf(sprintfBuf, 225, "QID details: ");
log->WriteAll(sprintfBuf);
log->WriteAll("============");
// display UNIQUEQUERYID_SEGMENTNUM
snprintf(sprintfBuf, 225, " Segment Num: " PFLL,queryIdAttrs[0].num_val_or_len);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_SEGMENTNAME
snprintf(sprintfBuf, 225, " Segment Name: %s",queryIdAttrs[1].string_val);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_CPU
snprintf(sprintfBuf, 225, " Cpu: " PFLL,queryIdAttrs[2].num_val_or_len);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_PIN
snprintf(sprintfBuf, 225, " Pin: " PFLL,queryIdAttrs[3].num_val_or_len);
log->WriteAll(sprintfBuf);
// UNIQUEQUERYID_EXESTARTTIME
short startTimeArray[8];
_int64 startTime = queryIdAttrs[4].num_val_or_len;
short error;
INTERPRETTIMESTAMP( CONVERTTIMESTAMP(startTime, 0, // GMT to LCT
-1, // use current node
&error), startTimeArray);
sprintf(sprintfBuf, " ExeStartTime: " PF64 "= %02d/%02d/%02d %02d:%02d:%02d.%03d%03d LCT",
startTime, startTimeArray[0],startTimeArray[1],startTimeArray[2],
startTimeArray[3], startTimeArray[4], startTimeArray[5],
startTimeArray[6], startTimeArray[7]);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_SESSIONNUM
sprintf(sprintfBuf," SessionNum: " PFLL,queryIdAttrs[5].num_val_or_len);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_USERNAME
sprintf(sprintfBuf," UserName: %s",queryIdAttrs[6].string_val);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_SESSIONNAME
if (strlen(queryIdAttrs[7].string_val) > 0)
sprintf(sprintfBuf," SessionName: %s",queryIdAttrs[7].string_val);
else
sprintf(sprintfBuf," SessionName: NULL");
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_QUERYNUM
sprintf(sprintfBuf," QueryNum: " PFLL,queryIdAttrs[8].num_val_or_len);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_STMTNAME:
sprintf(sprintfBuf," StmtName: %s",queryIdAttrs[9].string_val);
log->WriteAll(sprintfBuf);
// display UNIQUEQUERYID_SESSIONID:
sprintf(sprintfBuf," SessionId: %s",queryIdAttrs[10].string_val);
log->WriteAll(sprintfBuf);
log->WriteAll("");
}
return 0;
}