8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 23:23:02 +01:00

Refactor system package support.

This commit is contained in:
Adriano dos Santos Fernandes 2020-08-23 22:11:23 -03:00
parent ff5ea5fc94
commit a3aa2ba5dd
7 changed files with 261 additions and 160 deletions

View File

@ -1027,7 +1027,7 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::dateToTimeStampTz(const ISC_DATE& date, Callbacks
//-------------------------------------
TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, ISC_TIMESTAMP_TZ& aFrom, ISC_TIMESTAMP_TZ& aTo)
TimeZoneRuleIterator::TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& aFrom, const ISC_TIMESTAMP_TZ& aTo)
: id(aId),
icuLib(Jrd::UnicodeUtil::getConversionICU()),
toTicks(TimeStamp::timeStampToTicks(aTo.utc_timestamp))

View File

@ -136,7 +136,7 @@ public:
class TimeZoneRuleIterator
{
public:
TimeZoneRuleIterator(USHORT aId, ISC_TIMESTAMP_TZ& aFrom, ISC_TIMESTAMP_TZ& aTo);
TimeZoneRuleIterator(USHORT aId, const ISC_TIMESTAMP_TZ& aFrom, const ISC_TIMESTAMP_TZ& aTo);
~TimeZoneRuleIterator();
public:

View File

@ -22,8 +22,6 @@
#include "firebird.h"
#include "../jrd/SystemPackages.h"
#include "../jrd/ods.h"
#include "../jrd/ini.h"
#include "../jrd/TimeZone.h"
using namespace Firebird;
@ -32,73 +30,24 @@ using namespace Jrd;
namespace
{
struct SystemPackageInit
struct SystemPackagesInit
{
explicit SystemPackageInit(MemoryPool& pool)
: list(FB_NEW_POOL(pool) ObjectsArray<SystemPackage>(pool, {
SystemPackage(
pool,
"RDB$TIME_ZONE_UTIL",
ODS_13_0,
// procedures
{
SystemProcedure(
pool,
"TRANSITIONS",
[]
(ThrowStatusExceptionWrapper* status, IExternalContext* /*context*/,
IRoutineMetadata* /*metadata*/, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder)
{
return FB_NEW TimeZoneTransitionsProcedure(status, inBuilder, outBuilder);
},
prc_selectable,
// input parameters
{
{"RDB$TIME_ZONE_NAME", fld_tz_name, false},
{"RDB$FROM_TIMESTAMP", fld_timestamp_tz, false},
{"RDB$TO_TIMESTAMP", fld_timestamp_tz, false}
},
// output parameters
{
{"RDB$START_TIMESTAMP", fld_timestamp_tz, false},
{"RDB$END_TIMESTAMP", fld_timestamp_tz, false},
{"RDB$ZONE_OFFSET", fld_tz_offset, false},
{"RDB$DST_OFFSET", fld_tz_offset, false},
{"RDB$EFFECTIVE_OFFSET", fld_tz_offset, false}
}
)
},
// functions
{
SystemFunction(
pool,
"DATABASE_VERSION",
[]
(ThrowStatusExceptionWrapper* status, IExternalContext* /*context*/,
IRoutineMetadata* /*metadata*/, IMetadataBuilder* inBuilder, IMetadataBuilder* outBuilder)
{
return FB_NEW TimeZoneDatabaseVersionFunction(status, inBuilder, outBuilder);
},
// parameters
{},
{ fld_tz_db_version, false }
)
}
)
}))
explicit SystemPackagesInit(MemoryPool& pool)
: list(FB_NEW_POOL(pool) ObjectsArray<SystemPackage>(pool))
{
list->add(TimeZonePackage(pool));
}
static InitInstance<SystemPackageInit> INSTANCE;
static InitInstance<SystemPackagesInit> INSTANCE;
AutoPtr<ObjectsArray<SystemPackage> > list;
};
InitInstance<SystemPackageInit> SystemPackageInit::INSTANCE;
InitInstance<SystemPackagesInit> SystemPackagesInit::INSTANCE;
}
ObjectsArray<SystemPackage>& SystemPackage::get()
{
return *SystemPackageInit::INSTANCE().list.get();
return *SystemPackagesInit::INSTANCE().list.get();
}

View File

@ -29,6 +29,7 @@
#include "../common/classes/array.h"
#include "../common/classes/objects_array.h"
#include "../jrd/constants.h"
#include "../jrd/ini.h"
#include "firebird/Interface.h"
#include <initializer_list>
#include <functional>
@ -160,6 +161,145 @@ namespace Jrd
Firebird::ObjectsArray<SystemFunction> functions;
static Firebird::ObjectsArray<SystemPackage>& get();
private:
SystemPackage(const SystemPackage&) = delete;
SystemPackage& operator=(SystemPackage const&) = default;
};
class VoidMessage
{
public:
typedef void Type;
public:
static void setup(Firebird::ThrowStatusExceptionWrapper*, Firebird::IMetadataBuilder*)
{
}
};
template <
typename Input,
typename Output,
Firebird::IExternalResultSet* (*OpenFunction)(
Firebird::ThrowStatusExceptionWrapper*,
Firebird::IExternalContext*,
const typename Input::Type*,
typename Output::Type*
)
>
struct SystemProcedureFactory
{
class SystemProcedureImpl :
public
Firebird::DisposeIface<
Firebird::IExternalProcedureImpl<
SystemProcedureImpl,
Firebird::ThrowStatusExceptionWrapper
>
>
{
public:
SystemProcedureImpl(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IMetadataBuilder* inBuilder, Firebird::IMetadataBuilder* outBuilder)
{
Input::setup(status, inBuilder);
Output::setup(status, outBuilder);
}
public:
void dispose() override
{
delete this;
}
public:
void getCharSet(Firebird::ThrowStatusExceptionWrapper* status, Firebird::IExternalContext* context,
char* name, unsigned nameSize) override
{
strncpy(name, "UTF8", nameSize);
}
Firebird::IExternalResultSet* open(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context, void* inMsg, void* outMsg) override
{
return OpenFunction(status, context,
static_cast<typename Input::Type*>(inMsg),
static_cast<typename Output::Type*>(outMsg));
}
};
SystemProcedureImpl* operator()(
Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* /*context*/,
Firebird::IRoutineMetadata* /*metadata*/,
Firebird::IMetadataBuilder* inBuilder,
Firebird::IMetadataBuilder* outBuilder)
{
return FB_NEW SystemProcedureImpl(status, inBuilder, outBuilder);
}
};
template <
typename Input,
typename Output,
void (*ExecFunction)(
Firebird::ThrowStatusExceptionWrapper*,
Firebird::IExternalContext*,
const typename Input::Type*,
typename Output::Type*
)
>
struct SystemFunctionFactory
{
class SystemFunctionImpl :
public
Firebird::DisposeIface<
Firebird::IExternalFunctionImpl<
SystemFunctionImpl,
Firebird::ThrowStatusExceptionWrapper
>
>
{
public:
SystemFunctionImpl(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IMetadataBuilder* inBuilder, Firebird::IMetadataBuilder* outBuilder)
{
Input::setup(status, inBuilder);
Output::setup(status, outBuilder);
}
public:
void dispose() override
{
delete this;
}
public:
void getCharSet(Firebird::ThrowStatusExceptionWrapper* status, Firebird::IExternalContext* context,
char* name, unsigned nameSize) override
{
strncpy(name, "UTF8", nameSize);
}
void execute(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context, void* inMsg, void* outMsg) override
{
ExecFunction(status, context,
static_cast<typename Input::Type*>(inMsg),
static_cast<typename Output::Type*>(outMsg));
}
};
SystemFunctionImpl* operator()(
Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* /*context*/,
Firebird::IRoutineMetadata* /*metadata*/,
Firebird::IMetadataBuilder* inBuilder,
Firebird::IMetadataBuilder* outBuilder)
{
return FB_NEW SystemFunctionImpl(status, inBuilder, outBuilder);
}
};
} // namespace Jrd

View File

@ -80,12 +80,10 @@ bool TimeZonesTableScan::retrieveRecord(thread_db* tdbb, jrd_rel* relation,
//--------------------------------------
TimeZoneTransitionsResultSet::TimeZoneTransitionsResultSet(ThrowStatusExceptionWrapper* status,
IExternalContext* context, void* inMsg, void* outMsg)
: out(static_cast<TimeZoneTransitionsOutput::Type*>(outMsg))
TimeZonePackage::TransitionsResultSet::TransitionsResultSet(ThrowStatusExceptionWrapper* status,
IExternalContext* context, const TransitionsInput::Type* in, TransitionsOutput::Type* aOut)
: out(aOut)
{
TimeZoneTransitionsInput::Type* in = static_cast<TimeZoneTransitionsInput::Type*>(inMsg);
out->startTimestampNull = out->endTimestampNull = out->zoneOffsetNull =
out->dstOffsetNull = out->effectiveOffsetNull = FB_FALSE;
@ -94,7 +92,7 @@ TimeZoneTransitionsResultSet::TimeZoneTransitionsResultSet(ThrowStatusExceptionW
iterator = FB_NEW TimeZoneRuleIterator(tzId, in->fromTimestamp, in->toTimestamp);
}
FB_BOOLEAN TimeZoneTransitionsResultSet::fetch(ThrowStatusExceptionWrapper* status)
FB_BOOLEAN TimeZonePackage::TransitionsResultSet::fetch(ThrowStatusExceptionWrapper* status)
{
if (!iterator->next())
return false;
@ -112,14 +110,59 @@ FB_BOOLEAN TimeZoneTransitionsResultSet::fetch(ThrowStatusExceptionWrapper* stat
//--------------------------------------
void TimeZoneDatabaseVersionFunction::execute(ThrowStatusExceptionWrapper* status,
IExternalContext* context, void* inMsg, void* outMsg)
void TimeZonePackage::databaseVersionFunction(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context, const void*, DatabaseVersionOutput::Type* out)
{
TimeZoneDatabaseVersionOutput::Type* out = static_cast<TimeZoneDatabaseVersionOutput::Type*>(outMsg);
string str;
TimeZoneUtil::getDatabaseVersion(str);
out->versionNull = FB_FALSE;
out->version.set(str.c_str());
}
//--------------------------------------
TimeZonePackage::TimeZonePackage(Firebird::MemoryPool& pool)
: SystemPackage(
pool,
"RDB$TIME_ZONE_UTIL",
ODS_13_0,
// procedures
{
SystemProcedure(
pool,
"TRANSITIONS",
SystemProcedureFactory<TransitionsInput, TransitionsOutput, transitionsProcedure>(),
prc_selectable,
// input parameters
{
{"RDB$TIME_ZONE_NAME", fld_tz_name, false},
{"RDB$FROM_TIMESTAMP", fld_timestamp_tz, false},
{"RDB$TO_TIMESTAMP", fld_timestamp_tz, false}
},
// output parameters
{
{"RDB$START_TIMESTAMP", fld_timestamp_tz, false},
{"RDB$END_TIMESTAMP", fld_timestamp_tz, false},
{"RDB$ZONE_OFFSET", fld_tz_offset, false},
{"RDB$DST_OFFSET", fld_tz_offset, false},
{"RDB$EFFECTIVE_OFFSET", fld_tz_offset, false}
}
)
},
// functions
{
SystemFunction(
pool,
"DATABASE_VERSION",
SystemFunctionFactory<VoidMessage, DatabaseVersionOutput, databaseVersionFunction>(),
// parameters
{},
{fld_tz_db_version, false}
)
}
)
{
}

View File

@ -27,6 +27,7 @@
#include "firebird/Message.h"
#include "../common/classes/fb_string.h"
#include "../jrd/Monitoring.h"
#include "../jrd/SystemPackages.h"
#include "../jrd/recsrc/RecordSource.h"
namespace Jrd {
@ -42,7 +43,7 @@ public:
TimeZoneSnapshot(thread_db* tdbb, MemoryPool& pool);
};
class TimeZonesTableScan: public VirtualTableScan
class TimeZonesTableScan : public VirtualTableScan
{
public:
TimeZonesTableScan(CompilerScratch* csb, const Firebird::string& alias, StreamType stream, jrd_rel* relation);
@ -53,105 +54,68 @@ protected:
};
FB_MESSAGE(TimeZoneTransitionsInput, Firebird::ThrowStatusExceptionWrapper,
(FB_INTL_VARCHAR(MAX_SQL_IDENTIFIER_LEN, CS_METADATA), timeZoneName)
(FB_TIMESTAMP_TZ, fromTimestamp)
(FB_TIMESTAMP_TZ, toTimestamp)
);
FB_MESSAGE(TimeZoneTransitionsOutput, Firebird::ThrowStatusExceptionWrapper,
(FB_TIMESTAMP_TZ, startTimestamp)
(FB_TIMESTAMP_TZ, endTimestamp)
(FB_SMALLINT, zoneOffset)
(FB_SMALLINT, dstOffset)
(FB_SMALLINT, effectiveOffset)
);
class TimeZoneTransitionsResultSet :
public Firebird::DisposeIface<
Firebird::IExternalResultSetImpl<TimeZoneTransitionsResultSet, Firebird::ThrowStatusExceptionWrapper> >
class TimeZonePackage : public SystemPackage
{
public:
TimeZoneTransitionsResultSet(Firebird::ThrowStatusExceptionWrapper* status, Firebird::IExternalContext* context,
void* inMsg, void* outMsg);
public:
void dispose() override
{
delete this;
}
public:
FB_BOOLEAN fetch(Firebird::ThrowStatusExceptionWrapper* status) override;
TimeZonePackage(Firebird::MemoryPool& pool);
private:
TimeZoneTransitionsOutput::Type* out;
Firebird::AutoPtr<Firebird::TimeZoneRuleIterator> iterator;
};
FB_MESSAGE(TransitionsInput, Firebird::ThrowStatusExceptionWrapper,
(FB_INTL_VARCHAR(MAX_SQL_IDENTIFIER_LEN, CS_METADATA), timeZoneName)
(FB_TIMESTAMP_TZ, fromTimestamp)
(FB_TIMESTAMP_TZ, toTimestamp)
);
class TimeZoneTransitionsProcedure :
public Firebird::DisposeIface<
Firebird::IExternalProcedureImpl<TimeZoneTransitionsProcedure, Firebird::ThrowStatusExceptionWrapper> >
{
public:
TimeZoneTransitionsProcedure(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IMetadataBuilder* inBuilder, Firebird::IMetadataBuilder* outBuilder)
FB_MESSAGE(TransitionsOutput, Firebird::ThrowStatusExceptionWrapper,
(FB_TIMESTAMP_TZ, startTimestamp)
(FB_TIMESTAMP_TZ, endTimestamp)
(FB_SMALLINT, zoneOffset)
(FB_SMALLINT, dstOffset)
(FB_SMALLINT, effectiveOffset)
);
class TransitionsResultSet :
public
Firebird::DisposeIface<
Firebird::IExternalResultSetImpl<
TransitionsResultSet,
Firebird::ThrowStatusExceptionWrapper
>
>
{
TimeZoneTransitionsInput::setup(status, inBuilder);
TimeZoneTransitionsOutput::setup(status, outBuilder);
public:
TransitionsResultSet(Firebird::ThrowStatusExceptionWrapper* status, Firebird::IExternalContext* context,
const TransitionsInput::Type* in, TransitionsOutput::Type* out);
public:
void dispose() override
{
delete this;
}
public:
FB_BOOLEAN fetch(Firebird::ThrowStatusExceptionWrapper* status) override;
private:
TransitionsOutput::Type* out;
Firebird::AutoPtr<Firebird::TimeZoneRuleIterator> iterator;
};
static Firebird::IExternalResultSet* transitionsProcedure(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context,
const TransitionsInput::Type* in, TransitionsOutput::Type* out)
{
return FB_NEW TransitionsResultSet(status, context, in, out);
}
public:
void dispose() override
{
delete this;
}
//----------
public:
void getCharSet(Firebird::ThrowStatusExceptionWrapper* status, Firebird::IExternalContext* context,
char* name, unsigned nameSize) override
{
strncpy(name, "UTF8", nameSize);
}
FB_MESSAGE(DatabaseVersionOutput, Firebird::ThrowStatusExceptionWrapper,
(FB_INTL_VARCHAR(10, CS_ASCII), version)
);
Firebird::IExternalResultSet* open(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context, void* inMsg, void* outMsg) override
{
return FB_NEW TimeZoneTransitionsResultSet(status, context, inMsg, outMsg);
}
};
FB_MESSAGE(TimeZoneDatabaseVersionOutput, Firebird::ThrowStatusExceptionWrapper,
(FB_INTL_VARCHAR(10, CS_ASCII), version)
);
class TimeZoneDatabaseVersionFunction :
public Firebird::DisposeIface<
Firebird::IExternalFunctionImpl<TimeZoneDatabaseVersionFunction, Firebird::ThrowStatusExceptionWrapper> >
{
public:
TimeZoneDatabaseVersionFunction(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IMetadataBuilder* inBuilder, Firebird::IMetadataBuilder* outBuilder)
{
TimeZoneDatabaseVersionOutput::setup(status, outBuilder);
}
public:
void dispose() override
{
delete this;
}
public:
void getCharSet(Firebird::ThrowStatusExceptionWrapper* status, Firebird::IExternalContext* context,
char* name, unsigned nameSize) override
{
strncpy(name, "UTF8", nameSize);
}
void execute(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context, void* inMsg, void* outMsg) override;
static void databaseVersionFunction(Firebird::ThrowStatusExceptionWrapper* status,
Firebird::IExternalContext* context, const void* in, DatabaseVersionOutput::Type* out);
};

View File

@ -25,6 +25,9 @@
as well as by ini.epp in JRD. Make sure that any
changes are compatible in both places. */
#ifndef JRD_INI_H
#define JRD_INI_H
#include "../common/intlobj_new.h"
#include "../jrd/intl.h"
#include "../intl/country_codes.h"
@ -189,3 +192,5 @@ static const rtyp types[] =
};
#undef TYPE
#endif // JRD_INI_H