2008-07-03 14:02:54 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Firebird exceptions classes
|
|
|
|
* MODULE: StatusArg.cpp
|
|
|
|
* DESCRIPTION: Build status vector with variable number of elements
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Initial
|
|
|
|
* Developer's Public License Version 1.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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed AS IS,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing rights
|
|
|
|
* and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Alex Peshkov
|
|
|
|
* for the Firebird Open Source RDBMS project.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2008 Alex Peshkov <peshkoff at mail.ru>
|
|
|
|
* and all contributors signed below.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
|
|
|
#include "../common/StatusArg.h"
|
2010-10-12 10:02:57 +02:00
|
|
|
#include "../common/utils_proto.h"
|
2008-07-03 14:02:54 +02:00
|
|
|
|
|
|
|
#include "../common/classes/fb_string.h"
|
|
|
|
#include "../common/classes/MetaName.h"
|
2008-11-23 15:34:39 +01:00
|
|
|
#include "../common/classes/alloc.h"
|
2008-07-03 14:02:54 +02:00
|
|
|
#include "fb_exception.h"
|
|
|
|
#include "gen/iberror.h"
|
2011-06-29 11:41:47 +02:00
|
|
|
#include "firebird/Interface.h"
|
2014-07-24 08:41:38 +02:00
|
|
|
#include "../common/msg_encode.h"
|
2012-01-19 06:42:04 +01:00
|
|
|
|
2008-11-30 18:11:56 +01:00
|
|
|
#ifdef WIN_NT
|
|
|
|
#include <windows.h>
|
|
|
|
#else
|
|
|
|
#include <errno.h>
|
|
|
|
#endif
|
|
|
|
|
2012-01-19 06:42:04 +01:00
|
|
|
namespace {
|
|
|
|
// Didn't want to bring dyn.h and friends here.
|
|
|
|
const int DYN_MSG_FAC = 8;
|
|
|
|
}
|
|
|
|
|
2008-07-03 14:02:54 +02:00
|
|
|
namespace Firebird {
|
|
|
|
|
|
|
|
namespace Arg {
|
|
|
|
|
2014-08-27 11:24:30 +02:00
|
|
|
Base::Base(ISC_STATUS k, ISC_STATUS c) throw(Firebird::BadAlloc) :
|
2008-11-23 22:54:56 +01:00
|
|
|
implementation(FB_NEW(*getDefaultMemoryPool()) ImplBase(k, c))
|
|
|
|
{
|
|
|
|
}
|
2008-07-06 18:42:52 +02:00
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
StatusVector::ImplStatusVector::ImplStatusVector(const ISC_STATUS* s) throw() : Base::ImplBase(0, 0)
|
2008-09-11 15:06:31 +02:00
|
|
|
{
|
2009-08-05 08:27:57 +02:00
|
|
|
fb_assert(s);
|
|
|
|
|
2008-09-11 15:06:31 +02:00
|
|
|
clear();
|
|
|
|
// special case - empty initialized status vector, no warnings
|
|
|
|
if (s[0] != isc_arg_gds || s[1] != 0 || s[2] != 0)
|
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
append(s, FB_NELEM(m_status_vector) - 1);
|
2008-09-11 15:06:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-27 11:24:30 +02:00
|
|
|
StatusVector::ImplStatusVector::ImplStatusVector(const IStatus* s) throw() : Base::ImplBase(0, 0)
|
|
|
|
{
|
|
|
|
fb_assert(s);
|
|
|
|
|
|
|
|
clear();
|
2014-10-14 09:31:48 +02:00
|
|
|
|
|
|
|
if (s->getStatus() & IStatus::FB_HAS_ERRORS)
|
2014-08-27 11:24:30 +02:00
|
|
|
append(s->getErrors(), FB_NELEM(m_status_vector) - 1);
|
2014-10-14 09:31:48 +02:00
|
|
|
|
|
|
|
if (s->getStatus() & IStatus::FB_HAS_WARNINGS)
|
2014-08-27 11:24:30 +02:00
|
|
|
append(s->getWarnings(), FB_NELEM(m_status_vector) - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
StatusVector::StatusVector(ISC_STATUS k, ISC_STATUS c) throw(Firebird::BadAlloc) :
|
2008-11-23 15:34:39 +01:00
|
|
|
Base(FB_NEW(*getDefaultMemoryPool()) ImplStatusVector(k, c))
|
2008-12-05 02:20:14 +01:00
|
|
|
{
|
2008-10-31 12:14:37 +01:00
|
|
|
operator<<(*(static_cast<Base*>(this)));
|
|
|
|
}
|
|
|
|
|
2014-08-27 11:24:30 +02:00
|
|
|
StatusVector::StatusVector(const ISC_STATUS* s) throw(Firebird::BadAlloc) :
|
|
|
|
Base(FB_NEW(*getDefaultMemoryPool()) ImplStatusVector(s))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
StatusVector::StatusVector(const IStatus* s) throw(Firebird::BadAlloc) :
|
2008-11-23 22:54:56 +01:00
|
|
|
Base(FB_NEW(*getDefaultMemoryPool()) ImplStatusVector(s))
|
|
|
|
{
|
|
|
|
}
|
2008-10-31 12:14:37 +01:00
|
|
|
|
2014-08-27 11:24:30 +02:00
|
|
|
StatusVector::StatusVector() throw(Firebird::BadAlloc) :
|
2008-11-23 22:54:56 +01:00
|
|
|
Base(FB_NEW(*getDefaultMemoryPool()) ImplStatusVector(0, 0))
|
|
|
|
{
|
|
|
|
}
|
2008-10-31 12:14:37 +01:00
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::clear() throw()
|
2008-10-31 12:14:37 +01:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
m_length = 0;
|
|
|
|
m_warning = 0;
|
|
|
|
m_status_vector[0] = isc_arg_end;
|
2008-10-31 12:14:37 +01:00
|
|
|
}
|
|
|
|
|
2011-10-04 14:51:57 +02:00
|
|
|
bool StatusVector::ImplStatusVector::compare(const StatusVector& v) const throw()
|
|
|
|
{
|
|
|
|
return m_length == v.length() &&
|
2011-10-07 04:33:02 +02:00
|
|
|
memcmp(m_status_vector, v.value(), m_length * sizeof(ISC_STATUS)) == 0;
|
2011-10-04 14:51:57 +02:00
|
|
|
}
|
|
|
|
|
2009-12-06 02:34:57 +01:00
|
|
|
void StatusVector::ImplStatusVector::makePermanent() throw()
|
|
|
|
{
|
|
|
|
makePermanentVector(m_status_vector);
|
|
|
|
}
|
|
|
|
|
2012-11-01 12:40:18 +01:00
|
|
|
void StatusVector::ImplStatusVector::assign(const Exception& ex) throw()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
ex.stuff_exception(m_status_vector);
|
|
|
|
m_length = fb_utils::statusLength(m_status_vector);
|
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::append(const StatusVector& v) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
ImplStatusVector newVector(getKind(), getCode());
|
2008-07-11 04:37:23 +02:00
|
|
|
|
2008-07-10 17:46:41 +02:00
|
|
|
if (newVector.appendErrors(this))
|
2008-07-11 04:37:23 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
if (newVector.appendErrors(v.implementation))
|
2008-07-11 04:37:23 +02:00
|
|
|
{
|
2008-07-10 17:46:41 +02:00
|
|
|
if (newVector.appendWarnings(this))
|
2008-11-23 15:34:39 +01:00
|
|
|
newVector.appendWarnings(v.implementation);
|
2008-07-11 04:37:23 +02:00
|
|
|
}
|
|
|
|
}
|
2008-12-05 02:20:14 +01:00
|
|
|
|
2008-07-10 17:46:41 +02:00
|
|
|
*this = newVector;
|
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
bool StatusVector::ImplStatusVector::appendErrors(const ImplBase* const v) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
return append(v->value(), v->firstWarning() ? v->firstWarning() : v->length());
|
2008-12-05 02:20:14 +01:00
|
|
|
}
|
2008-07-10 17:46:41 +02:00
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
bool StatusVector::ImplStatusVector::appendWarnings(const ImplBase* const v) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
if (! v->firstWarning())
|
2008-07-10 17:46:41 +02:00
|
|
|
return true;
|
2008-11-23 15:34:39 +01:00
|
|
|
return append(v->value() + v->firstWarning(), v->length() - v->firstWarning());
|
2008-12-05 02:20:14 +01:00
|
|
|
}
|
2008-07-10 17:46:41 +02:00
|
|
|
|
2009-11-05 12:56:26 +01:00
|
|
|
bool StatusVector::ImplStatusVector::append(const ISC_STATUS* const from, const unsigned int count) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2009-08-05 08:27:57 +02:00
|
|
|
// CVC: I didn't expect count to be zero but it's, in some calls
|
|
|
|
fb_assert(count >= 0 && count <= ISC_STATUS_LENGTH);
|
|
|
|
if (!count)
|
|
|
|
return true; // not sure it's the best option here
|
|
|
|
|
2010-10-12 10:02:57 +02:00
|
|
|
unsigned int copied =
|
|
|
|
fb_utils::copyStatus(&m_status_vector[m_length], FB_NELEM(m_status_vector) - m_length, from, count);
|
2008-07-10 17:46:41 +02:00
|
|
|
m_length += copied;
|
2008-07-11 04:37:23 +02:00
|
|
|
|
2014-08-27 11:24:30 +02:00
|
|
|
if (!m_warning)
|
|
|
|
{
|
|
|
|
for (unsigned n = 0; n < m_length; )
|
|
|
|
{
|
|
|
|
if (m_status_vector[n] == isc_arg_warning)
|
|
|
|
{
|
|
|
|
m_warning = n;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
n += (m_status_vector[n] == isc_arg_cstring) ? 3 : 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-05 12:56:26 +01:00
|
|
|
return copied == count;
|
2008-07-10 17:46:41 +02:00
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::shiftLeft(const Base& arg) throw()
|
2008-07-03 14:02:54 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
if (m_length < FB_NELEM(m_status_vector) - 2)
|
2008-07-03 14:02:54 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
m_status_vector[m_length++] = arg.getKind();
|
|
|
|
m_status_vector[m_length++] = arg.getCode();
|
2008-07-03 14:02:54 +02:00
|
|
|
m_status_vector[m_length] = isc_arg_end;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::shiftLeft(const Warning& arg) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-07-12 10:06:19 +02:00
|
|
|
const int cur = m_warning ? 0 : m_length;
|
2008-11-23 15:34:39 +01:00
|
|
|
shiftLeft(*static_cast<const Base*>(&arg));
|
2008-07-10 17:46:41 +02:00
|
|
|
if (cur && m_status_vector[cur] == isc_arg_warning)
|
|
|
|
m_warning = cur;
|
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::shiftLeft(const char* text) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
shiftLeft(Str(text));
|
2008-07-10 17:46:41 +02:00
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::shiftLeft(const AbstractString& text) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
shiftLeft(Str(text));
|
2008-07-10 17:46:41 +02:00
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
void StatusVector::ImplStatusVector::shiftLeft(const MetaName& text) throw()
|
2008-07-10 17:46:41 +02:00
|
|
|
{
|
2008-11-23 15:34:39 +01:00
|
|
|
shiftLeft(Str(text));
|
2008-07-10 17:46:41 +02:00
|
|
|
}
|
|
|
|
|
2008-07-03 14:02:54 +02:00
|
|
|
void StatusVector::raise() const
|
|
|
|
{
|
|
|
|
if (hasData())
|
|
|
|
{
|
|
|
|
status_exception::raise(*this);
|
|
|
|
}
|
2009-08-05 08:27:57 +02:00
|
|
|
status_exception::raise(Gds(isc_random) << Str("Attempt to raise empty exception"));
|
2008-07-03 14:02:54 +02:00
|
|
|
}
|
|
|
|
|
2008-11-23 15:34:39 +01:00
|
|
|
ISC_STATUS StatusVector::ImplStatusVector::copyTo(ISC_STATUS* dest) const throw()
|
2008-08-15 13:21:47 +02:00
|
|
|
{
|
|
|
|
if (hasData())
|
|
|
|
{
|
2009-06-04 11:32:08 +02:00
|
|
|
memcpy(dest, value(), (length() + 1u) * sizeof(ISC_STATUS));
|
2008-08-15 13:21:47 +02:00
|
|
|
}
|
2009-08-05 08:27:57 +02:00
|
|
|
else
|
|
|
|
{
|
2008-08-15 13:21:47 +02:00
|
|
|
dest[0] = isc_arg_gds;
|
|
|
|
dest[1] = FB_SUCCESS;
|
|
|
|
dest[2] = isc_arg_end;
|
|
|
|
}
|
|
|
|
return dest[1];
|
|
|
|
}
|
|
|
|
|
2011-06-29 11:41:47 +02:00
|
|
|
ISC_STATUS StatusVector::ImplStatusVector::copyTo(IStatus* dest) const throw()
|
|
|
|
{
|
2014-08-27 11:24:30 +02:00
|
|
|
dest->init();
|
2011-06-29 11:41:47 +02:00
|
|
|
if (hasData())
|
|
|
|
{
|
2014-08-27 11:24:30 +02:00
|
|
|
const ISC_STATUS* v = m_status_vector;
|
|
|
|
unsigned int length = m_length;
|
|
|
|
unsigned int warning = m_warning;
|
|
|
|
|
|
|
|
if (v[warning] == isc_arg_warning)
|
|
|
|
{
|
2014-09-29 13:03:47 +02:00
|
|
|
dest->setWarnings2(length - warning, &v[warning]);
|
2014-08-27 11:24:30 +02:00
|
|
|
if (warning)
|
2014-09-29 13:03:47 +02:00
|
|
|
dest->setErrors2(warning, v);
|
2014-08-27 11:24:30 +02:00
|
|
|
}
|
|
|
|
else
|
2014-09-29 13:03:47 +02:00
|
|
|
dest->setErrors2(length, v);
|
2011-06-29 11:41:47 +02:00
|
|
|
}
|
2014-08-27 11:24:30 +02:00
|
|
|
return m_status_vector[1];
|
2011-06-29 11:41:47 +02:00
|
|
|
}
|
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Gds::Gds(ISC_STATUS s) throw() :
|
2008-07-03 14:02:54 +02:00
|
|
|
StatusVector(isc_arg_gds, s) { }
|
|
|
|
|
2012-01-19 06:42:04 +01:00
|
|
|
PrivateDyn::PrivateDyn(ISC_STATUS codeWithoutFacility) throw() :
|
|
|
|
Gds(ENCODE_ISC_MSG(codeWithoutFacility, DYN_MSG_FAC)) { }
|
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Num::Num(ISC_STATUS s) throw() :
|
2008-07-03 14:02:54 +02:00
|
|
|
Base(isc_arg_number, s) { }
|
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Interpreted::Interpreted(const char* text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
StatusVector(isc_arg_interpreted, (ISC_STATUS)(IPTR) text) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Interpreted::Interpreted(const AbstractString& text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
StatusVector(isc_arg_interpreted, (ISC_STATUS)(IPTR) text.c_str()) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Unix::Unix(ISC_STATUS s) throw() :
|
2008-07-03 14:02:54 +02:00
|
|
|
Base(isc_arg_unix, s) { }
|
|
|
|
|
2009-06-09 15:58:06 +02:00
|
|
|
Mach::Mach(ISC_STATUS s) throw() :
|
|
|
|
Base(isc_arg_next_mach, s) { }
|
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Windows::Windows(ISC_STATUS s) throw() :
|
2008-07-03 14:02:54 +02:00
|
|
|
Base(isc_arg_win32, s) { }
|
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Warning::Warning(ISC_STATUS s) throw() :
|
2008-07-03 14:02:54 +02:00
|
|
|
StatusVector(isc_arg_warning, s) { }
|
|
|
|
|
2010-01-26 08:32:12 +01:00
|
|
|
// Str overloading.
|
2008-12-05 02:20:14 +01:00
|
|
|
Str::Str(const char* text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
Base(isc_arg_string, (ISC_STATUS)(IPTR) text) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Str::Str(const AbstractString& text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
Base(isc_arg_string, (ISC_STATUS)(IPTR) text.c_str()) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
Str::Str(const MetaName& text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
Base(isc_arg_string, (ISC_STATUS)(IPTR) text.c_str()) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
SqlState::SqlState(const char* text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
Base(isc_arg_sql_state, (ISC_STATUS)(IPTR) text) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
SqlState::SqlState(const AbstractString& text) throw() :
|
2008-07-06 12:56:34 +02:00
|
|
|
Base(isc_arg_sql_state, (ISC_STATUS)(IPTR) text.c_str()) { }
|
2008-07-03 14:02:54 +02:00
|
|
|
|
2008-12-05 02:20:14 +01:00
|
|
|
OsError::OsError() throw() :
|
2008-11-30 18:11:56 +01:00
|
|
|
#ifdef WIN_NT
|
|
|
|
Base(isc_arg_win32, GetLastError()) { }
|
|
|
|
#else
|
|
|
|
Base(isc_arg_unix, errno) { }
|
|
|
|
#endif
|
2014-04-04 17:57:18 +02:00
|
|
|
|
|
|
|
OsError::OsError(ISC_STATUS s) throw() :
|
|
|
|
#ifdef WIN_NT
|
|
|
|
Base(isc_arg_win32, s) { }
|
|
|
|
#else
|
|
|
|
Base(isc_arg_unix, s) { }
|
|
|
|
#endif
|
2008-07-03 14:02:54 +02:00
|
|
|
} // namespace Arg
|
|
|
|
|
|
|
|
} // namespace Firebird
|