From 050cea380efd4a3aeed764b12503f42c38e0f477 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Wed, 14 Nov 2018 13:12:08 -0200 Subject: [PATCH 01/13] - Change MON$ TIMESTAMP fields to TIMESTAMP WITH TIME ZONE. - Added fb_info_creation_timestamp_tz. - Make timeouts work when server time zone is changed. --- src/common/TimeZoneUtil.cpp | 15 +++++++++++++++ src/common/TimeZoneUtil.h | 1 + src/jrd/Attachment.cpp | 28 +++++++++++++++++----------- src/jrd/Attachment.h | 10 +++++----- src/jrd/Database.h | 4 ++-- src/jrd/Monitoring.cpp | 20 ++++++++++---------- src/jrd/Monitoring.h | 2 +- src/jrd/inf.cpp | 13 ++++++++++++- src/jrd/inf_pub.h | 2 ++ src/jrd/jrd.cpp | 24 ++++++++++++------------ src/jrd/jrd.h | 4 ++-- src/jrd/pag.cpp | 7 ++++--- src/jrd/relations.h | 10 +++++----- src/jrd/req.h | 8 ++++++++ src/jrd/tra.h | 4 ++-- 15 files changed, 98 insertions(+), 54 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index 83c93c8ad4..4a5a53622d 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -609,6 +609,21 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentTimeStampUtc() return tsTz; } +ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentTimeStampGmt() +{ + //// TODO: Make this function does not depend on local time. + TimeStamp now = TimeStamp::getCurrentTimeStamp(); + + ISC_TIMESTAMP_TZ tsTz; + tsTz.utc_timestamp = now.value(); + tsTz.time_zone = getSystemTimeZone(); + localTimeStampToUtc(tsTz); + + tsTz.time_zone = GMT_ZONE; + + return tsTz; +} + void TimeZoneUtil::validateTimeStampUtc(NoThrowTimeStamp& ts) { if (ts.isEmpty()) diff --git a/src/common/TimeZoneUtil.h b/src/common/TimeZoneUtil.h index 85d1c8be9e..2184dd1a05 100644 --- a/src/common/TimeZoneUtil.h +++ b/src/common/TimeZoneUtil.h @@ -103,6 +103,7 @@ public: static void decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, struct tm* times, int* fractions = NULL); static ISC_TIMESTAMP_TZ getCurrentTimeStampUtc(); + static ISC_TIMESTAMP_TZ getCurrentTimeStampGmt(); static void validateTimeStampUtc(NoThrowTimeStamp& ts); diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 9d38a333ef..7aed189b2d 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -212,7 +212,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb) att_base_stats(*pool), att_working_directory(*pool), att_filename(*pool), - att_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()), + att_timestamp(TimeZoneUtil::getCurrentTimeStampUtc()), att_context_vars(*pool), ddlTriggersContext(*pool), att_network_protocol(*pool), @@ -952,20 +952,19 @@ void Attachment::setupIdleTimer(bool clear) } } -bool Attachment::getIdleTimerTimestamp(TimeStamp& ts) const +bool Attachment::getIdleTimerTimestamp(ISC_TIMESTAMP_TZ& ts) const { if (!att_idle_timer) return false; - time_t value = att_idle_timer->getExpiryTime(); + SINT64 value = att_idle_timer->getExpiryTime(); if (!value) return false; - struct tm* times = localtime(&value); - if (!times) - return false; + ts.utc_timestamp.timestamp_date = value / TimeStamp::ISC_TICKS_PER_DAY; + ts.utc_timestamp.timestamp_time = value % TimeStamp::ISC_TICKS_PER_DAY; + ts.time_zone = TimeZoneUtil::GMT_ZONE; - ts = TimeStamp::encode_timestamp(times); return true; } @@ -991,7 +990,11 @@ void Attachment::IdleTimer::handler() return; // If timer was reset to fire later, restart ITimer - time_t curTime = time(NULL); + + const ISC_TIMESTAMP currentTimeGmt = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; + const SINT64 curTime = currentTimeGmt.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + + (SINT64) currentTimeGmt.timestamp_time; + if (curTime < m_expTime) { reset(m_expTime - curTime); @@ -1025,8 +1028,11 @@ void Attachment::IdleTimer::reset(unsigned int timeout) return; } - const time_t curTime = time(NULL); - m_expTime = curTime + timeout; + const ISC_TIMESTAMP currentTimeGmt = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; + const SINT64 curTime = currentTimeGmt.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + + (SINT64) currentTimeGmt.timestamp_time; + + m_expTime = curTime + timeout * ISC_TIME_SECONDS_PRECISION; FbLocalStatus s; ITimerControl* timerCtrl = Firebird::TimerInterfacePtr(); @@ -1041,7 +1047,7 @@ void Attachment::IdleTimer::reset(unsigned int timeout) m_fireTime = 0; } - timerCtrl->start(&s, this, (m_expTime - curTime) * 1000 * 1000); + timerCtrl->start(&s, this, (m_expTime - curTime) * 100); check(&s); m_fireTime = m_expTime; } diff --git a/src/jrd/Attachment.h b/src/jrd/Attachment.h index c4009679b5..093b5124a8 100644 --- a/src/jrd/Attachment.h +++ b/src/jrd/Attachment.h @@ -336,7 +336,7 @@ public: Validation* att_validation; Firebird::PathName att_working_directory; // Current working directory is cached Firebird::PathName att_filename; // alias used to attach the database - const Firebird::TimeStamp att_timestamp; // Connection date and time + const ISC_TIMESTAMP_TZ att_timestamp; // Connection date and time Firebird::StringMap att_context_vars; // Context variables for the connection Firebird::Stack ddlTriggersContext; // Context variables for DDL trigger event Firebird::string att_network_protocol; // Network protocol used by client for connection @@ -488,7 +488,7 @@ public: void setupIdleTimer(bool clear); // returns time when idle timer will be expired, if set - bool getIdleTimerTimestamp(Firebird::TimeStamp& ts) const; + bool getIdleTimerTimestamp(ISC_TIMESTAMP_TZ& ts) const; // batches control void registerBatch(JBatch* b) @@ -522,15 +522,15 @@ private: // Set timeout, seconds void reset(unsigned int timeout); - time_t getExpiryTime() const + SINT64 getExpiryTime() const { return m_expTime; } private: Firebird::RefPtr m_attachment; - time_t m_fireTime; // when ITimer will fire, could be less than m_expTime - time_t m_expTime; // when actual idle timeout will expire + SINT64 m_fireTime; // when ITimer will fire, could be less than m_expTime + SINT64 m_expTime; // when actual idle timeout will expire }; unsigned int att_idle_timeout; // seconds diff --git a/src/jrd/Database.h b/src/jrd/Database.h index f6278a5666..440898bf34 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -424,7 +424,7 @@ public: TipCache* dbb_tip_cache; // cache of latest known state of all transactions in system BackupManager* dbb_backup_manager; // physical backup manager - Firebird::TimeStamp dbb_creation_date; // creation date + ISC_TIMESTAMP_TZ dbb_creation_date; // creation timestamp in GMT ExternalFileDirectoryList* dbb_external_file_directory_list; Firebird::RefPtr dbb_config; @@ -481,7 +481,7 @@ private: dbb_stats(*p), dbb_lock_owner_id(getLockOwnerId()), dbb_tip_cache(NULL), - dbb_creation_date(Firebird::TimeStamp::getCurrentTimeStamp()), + dbb_creation_date(Firebird::TimeZoneUtil::getCurrentTimeStampGmt()), dbb_external_file_directory_list(NULL), dbb_init_fini(FB_NEW_POOL(*getDefaultMemoryPool()) ExistenceRefMutex()), dbb_linger_seconds(0), diff --git a/src/jrd/Monitoring.cpp b/src/jrd/Monitoring.cpp index 58a6641925..bc6733c721 100644 --- a/src/jrd/Monitoring.cpp +++ b/src/jrd/Monitoring.cpp @@ -821,7 +821,7 @@ void Monitoring::putDatabase(thread_db* tdbb, SnapshotData::DumpRecord& record) temp = (database->dbb_flags & DBB_no_reserve) ? 0 : 1; record.storeInteger(f_mon_db_res_space, temp); // creation date - record.storeTimestamp(f_mon_db_created, database->dbb_creation_date); + record.storeTimestampTz(f_mon_db_created, database->dbb_creation_date); // database size record.storeInteger(f_mon_db_pages, PageSpace::actAlloc(database)); // database backup state @@ -925,7 +925,7 @@ void Monitoring::putAttachment(SnapshotData::DumpRecord& record, const Jrd::Atta // charset record.storeInteger(f_mon_att_charset_id, attachment->att_charset); // timestamp - record.storeTimestamp(f_mon_att_timestamp, attachment->att_timestamp); + record.storeTimestampTz(f_mon_att_timestamp, attachment->att_timestamp); // garbage collection flag temp = (attachment->att_flags & ATT_no_cleanup) ? 0 : 1; record.storeInteger(f_mon_att_gc, temp); @@ -949,9 +949,9 @@ void Monitoring::putAttachment(SnapshotData::DumpRecord& record, const Jrd::Atta // session idle timeout, seconds record.storeInteger(f_mon_att_idle_timeout, attachment->getIdleTimeout()); // when idle timer expires, NULL if not running - TimeStamp idleTimer; + ISC_TIMESTAMP_TZ idleTimer; if (attachment->getIdleTimerTimestamp(idleTimer)) - record.storeTimestamp(f_mon_att_idle_timer, idleTimer); + record.storeTimestampTz(f_mon_att_idle_timer, idleTimer); // statement timeout, milliseconds record.storeInteger(f_mon_att_stmt_timeout, attachment->getStatementTimeout()); @@ -990,7 +990,7 @@ void Monitoring::putTransaction(SnapshotData::DumpRecord& record, const jrd_tra* temp = transaction->tra_requests ? mon_state_active : mon_state_idle; record.storeInteger(f_mon_tra_state, temp); // timestamp - record.storeTimestamp(f_mon_tra_timestamp, transaction->tra_timestamp); + record.storeTimestampTz(f_mon_tra_timestamp, transaction->tra_timestamp); // top transaction record.storeInteger(f_mon_tra_top, transaction->tra_top); // oldest transaction @@ -1053,13 +1053,13 @@ void Monitoring::putRequest(SnapshotData::DumpRecord& record, const jrd_req* req const bool is_stalled = (request->req_flags & req_stall); record.storeInteger(f_mon_stmt_state, is_stalled ? mon_state_stalled : mon_state_active); record.storeInteger(f_mon_stmt_tra_id, request->req_transaction->tra_number); - record.storeTimestamp(f_mon_stmt_timestamp, request->getLocalTimeStamp().value()); + record.storeTimestampTz(f_mon_stmt_timestamp, request->getTimeStampTz()); - ISC_TIMESTAMP ts; + ISC_TIMESTAMP_TZ ts; if (request->req_timer && - request->req_timer->getExpireTimestamp(request->getLocalTimeStamp().value(), ts)) + request->req_timer->getExpireTimestamp(request->getTimeStampTz(), ts)) { - record.storeTimestamp(f_mon_stmt_timer, ts); + record.storeTimestampTz(f_mon_stmt_timer, ts); } } else @@ -1133,7 +1133,7 @@ void Monitoring::putCall(SnapshotData::DumpRecord& record, const jrd_req* reques } // timestamp - record.storeTimestamp(f_mon_call_timestamp, request->getLocalTimeStamp().value()); + record.storeTimestampTz(f_mon_call_timestamp, request->getTimeStampTz()); // source line/column if (request->req_src_line) { diff --git a/src/jrd/Monitoring.h b/src/jrd/Monitoring.h index 1e23f85d3c..bfda2bae7d 100644 --- a/src/jrd/Monitoring.h +++ b/src/jrd/Monitoring.h @@ -145,7 +145,7 @@ public: void storeTimestampTz(int field_id, const ISC_TIMESTAMP_TZ& value) { - storeField(field_id, VALUE_TIMESTAMP_TZ, sizeof(ISC_TIMESTAMP), &value); + storeField(field_id, VALUE_TIMESTAMP_TZ, sizeof(ISC_TIMESTAMP_TZ), &value); } void storeString(int field_id, const Firebird::string& value) diff --git a/src/jrd/inf.cpp b/src/jrd/inf.cpp index a17bcfd274..d80d582046 100644 --- a/src/jrd/inf.cpp +++ b/src/jrd/inf.cpp @@ -51,6 +51,7 @@ #include "../dsql/StmtNodes.h" #include "../jrd/license.h" #include "../jrd/cch_proto.h" +#include "../jrd/cvt_proto.h" #include "../jrd/inf_proto.h" #include "../common/isc_proto.h" #include "../jrd/opt_proto.h" @@ -487,13 +488,23 @@ void INF_database_info(thread_db* tdbb, case isc_info_creation_date: { - const ISC_TIMESTAMP ts = dbb->dbb_creation_date.value(); + const ISC_TIMESTAMP ts = TimeZoneUtil::cvtTimeStampTzToTimeStamp( + dbb->dbb_creation_date, &EngineCallbacks::instance); + length = INF_convert(ts.timestamp_date, p); p += length; length += INF_convert(ts.timestamp_time, p); } break; + case fb_info_creation_timestamp_tz: + length = INF_convert(dbb->dbb_creation_date.utc_timestamp.timestamp_date, p); + p += length; + length += INF_convert(dbb->dbb_creation_date.utc_timestamp.timestamp_time, p); + p += length; + length += INF_convert(dbb->dbb_creation_date.time_zone, p); + break; + case isc_info_no_reserve: *p++ = (dbb->dbb_flags & DBB_no_reserve) ? 1 : 0; length = p - buffer; diff --git a/src/jrd/inf_pub.h b/src/jrd/inf_pub.h index efedf8e636..e509cbe854 100644 --- a/src/jrd/inf_pub.h +++ b/src/jrd/inf_pub.h @@ -158,6 +158,8 @@ enum db_info_types fb_info_protocol_version = 137, fb_info_crypt_plugin = 138, + fb_info_creation_timestamp_tz = 139, + isc_info_db_last_value /* Leave this LAST! */ }; diff --git a/src/jrd/jrd.cpp b/src/jrd/jrd.cpp index 5dd5a2d424..41331e0a9a 100644 --- a/src/jrd/jrd.cpp +++ b/src/jrd/jrd.cpp @@ -8184,18 +8184,18 @@ unsigned int TimeoutTimer::timeToExpire() const return r > 0 ? r : 0; } -bool TimeoutTimer::getExpireTimestamp(const ISC_TIMESTAMP start, ISC_TIMESTAMP& exp) const +bool TimeoutTimer::getExpireTimestamp(const ISC_TIMESTAMP_TZ start, ISC_TIMESTAMP_TZ& exp) const { if (!m_started || m_expired) return false; - static const SINT64 ISC_TICKS_PER_DAY = 24 * 60 * 60 * ISC_TIME_SECONDS_PRECISION; - - SINT64 ticks = start.timestamp_date * ISC_TICKS_PER_DAY + start.timestamp_time; + SINT64 ticks = start.utc_timestamp.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + + start.utc_timestamp.timestamp_time; ticks += m_value * ISC_TIME_SECONDS_PRECISION / 1000; - exp.timestamp_date = ticks / ISC_TICKS_PER_DAY; - exp.timestamp_time = ticks % ISC_TICKS_PER_DAY; + exp.utc_timestamp.timestamp_date = ticks / TimeStamp::ISC_TICKS_PER_DAY; + exp.utc_timestamp.timestamp_time = ticks % TimeStamp::ISC_TICKS_PER_DAY; + exp.time_zone = start.time_zone; return true; } @@ -8256,18 +8256,18 @@ unsigned int TimeoutTimer::timeToExpire() const return r > 0 ? r : 0; } -bool TimeoutTimer::getExpireTimestamp(const ISC_TIMESTAMP start, ISC_TIMESTAMP& exp) const +bool TimeoutTimer::getExpireTimestamp(const ISC_TIMESTAMP_TZ start, ISC_TIMESTAMP_TZ& exp) const { if (!m_start) return false; - static const SINT64 ISC_TICKS_PER_DAY = 24 * 60 * 60 * ISC_TIME_SECONDS_PRECISION; - - SINT64 ticks = start.timestamp_date * ISC_TICKS_PER_DAY + start.timestamp_time; + SINT64 ticks = start.utc_timestamp.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + + start.utc_timestamp.timestamp_time; ticks += m_value * ISC_TIME_SECONDS_PRECISION / 1000; - exp.timestamp_date = ticks / ISC_TICKS_PER_DAY; - exp.timestamp_time = ticks % ISC_TICKS_PER_DAY; + exp.utc_timestamp.timestamp_date = ticks / TimeStamp::ISC_TICKS_PER_DAY; + exp.utc_timestamp.timestamp_time = ticks % TimeStamp::ISC_TICKS_PER_DAY; + exp.time_zone = start.time_zone; return true; } diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index d2b272f9a4..7021bcf5e0 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -385,7 +385,7 @@ public: unsigned int timeToExpire() const; // evaluate expire timestamp using start timestamp - bool getExpireTimestamp(const ISC_TIMESTAMP start, ISC_TIMESTAMP& exp) const; + bool getExpireTimestamp(const ISC_TIMESTAMP_TZ start, ISC_TIMESTAMP_TZ& exp) const; // set timeout value in milliseconds and secondary error code void setup(unsigned int value, ISC_STATUS error) @@ -429,7 +429,7 @@ public: unsigned int timeToExpire() const; // evaluate expire timestamp using start timestamp - bool getExpireTimestamp(const ISC_TIMESTAMP start, ISC_TIMESTAMP& exp) const; + bool getExpireTimestamp(const ISC_TIMESTAMP_TZ start, ISC_TIMESTAMP_TZ& exp) const; // set timeout value in milliseconds and secondary error code void setup(unsigned int value, ISC_STATUS error) diff --git a/src/jrd/pag.cpp b/src/jrd/pag.cpp index 20223c552d..af3f2fbeb9 100644 --- a/src/jrd/pag.cpp +++ b/src/jrd/pag.cpp @@ -281,7 +281,7 @@ USHORT PAG_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start) #ifdef SUPPORT_RAW_DEVICES // The following lines (taken from PAG_format_header) are needed to identify // this file in raw_devices_validate_database as a valid database attachment. - *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeStamp::getCurrentTimeStamp().value(); + *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; // should we include milliseconds or not? //TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0); @@ -953,7 +953,7 @@ void PAG_format_header(thread_db* tdbb) WIN window(HEADER_PAGE_NUMBER); header_page* header = (header_page*) CCH_fake(tdbb, &window, 1); header->hdr_header.pag_scn = 0; - *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeStamp::getCurrentTimeStamp().value(); + *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; // should we include milliseconds or not? //TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0); header->hdr_header.pag_type = pag_header; @@ -1150,7 +1150,8 @@ void PAG_header(thread_db* tdbb, bool info) dbb->dbb_oldest_snapshot = oldest_snapshot; dbb->dbb_attachment_id = header->hdr_attachment_id; - dbb->dbb_creation_date = *(ISC_TIMESTAMP*) header->hdr_creation_date; + dbb->dbb_creation_date.utc_timestamp = *(ISC_TIMESTAMP*) header->hdr_creation_date; + dbb->dbb_creation_date.time_zone = TimeZoneUtil::GMT_ZONE; if (header->hdr_flags & hdr_read_only) { diff --git a/src/jrd/relations.h b/src/jrd/relations.h index c880ea0587..64e7943615 100644 --- a/src/jrd/relations.h +++ b/src/jrd/relations.h @@ -486,7 +486,7 @@ RELATION(nam_mon_database, rel_mon_database, ODS_11_1, rel_virtual) FIELD(f_mon_db_read_only, nam_mon_read_only, fld_flag_nullable, 0, ODS_11_1) FIELD(f_mon_db_forced_writes, nam_mon_forced_writes, fld_flag_nullable, 0, ODS_11_1) FIELD(f_mon_db_res_space, nam_mon_res_space, fld_flag_nullable, 0, ODS_11_1) - FIELD(f_mon_db_created, nam_mon_created, fld_time, 0, ODS_11_1) + FIELD(f_mon_db_created, nam_mon_created, fld_timestamp_tz, 0, ODS_11_1) FIELD(f_mon_db_pages, nam_mon_pages, fld_counter, 0, ODS_11_1) FIELD(f_mon_db_stat_id, nam_mon_stat_id, fld_stat_id, 0, ODS_11_1) FIELD(f_mon_db_backup_state, nam_mon_backup_state, fld_backup_state, 0, ODS_11_1) @@ -507,7 +507,7 @@ RELATION(nam_mon_attachments, rel_mon_attachments, ODS_11_1, rel_virtual) FIELD(f_mon_att_remote_addr, nam_mon_remote_addr, fld_remote_addr, 0, ODS_11_1) FIELD(f_mon_att_remote_pid, nam_mon_remote_pid, fld_pid, 0, ODS_11_1) FIELD(f_mon_att_charset_id, nam_mon_charset_id, fld_charset_id, 0, ODS_11_1) - FIELD(f_mon_att_timestamp, nam_mon_timestamp, fld_time, 0, ODS_11_1) + FIELD(f_mon_att_timestamp, nam_mon_timestamp, fld_timestamp_tz, 0, ODS_11_1) FIELD(f_mon_att_gc, nam_mon_gc, fld_flag_nullable, 0, ODS_11_1) FIELD(f_mon_att_remote_process, nam_mon_remote_process, fld_file_name2, 0, ODS_11_1) FIELD(f_mon_att_stat_id, nam_mon_stat_id, fld_stat_id, 0, ODS_11_1) @@ -529,7 +529,7 @@ RELATION(nam_mon_transactions, rel_mon_transactions, ODS_11_1, rel_virtual) FIELD(f_mon_tra_id, nam_mon_tra_id, fld_trans_id, 0, ODS_11_1) FIELD(f_mon_tra_att_id, nam_mon_att_id, fld_att_id, 0, ODS_11_1) FIELD(f_mon_tra_state, nam_mon_state, fld_state, 0, ODS_11_1) - FIELD(f_mon_tra_timestamp, nam_mon_timestamp, fld_time, 0, ODS_11_1) + FIELD(f_mon_tra_timestamp, nam_mon_timestamp, fld_timestamp_tz, 0, ODS_11_1) FIELD(f_mon_tra_top, nam_mon_top, fld_trans_id, 0, ODS_11_1) FIELD(f_mon_tra_oit, nam_mon_oit, fld_trans_id, 0, ODS_11_1) FIELD(f_mon_tra_oat, nam_mon_oat, fld_trans_id, 0, ODS_11_1) @@ -547,7 +547,7 @@ RELATION(nam_mon_statements, rel_mon_statements, ODS_11_1, rel_virtual) FIELD(f_mon_stmt_att_id, nam_mon_att_id, fld_att_id, 0, ODS_11_1) FIELD(f_mon_stmt_tra_id, nam_mon_tra_id, fld_trans_id, 0, ODS_11_1) FIELD(f_mon_stmt_state, nam_mon_state, fld_state, 0, ODS_11_1) - FIELD(f_mon_stmt_timestamp, nam_mon_timestamp, fld_time, 0, ODS_11_1) + FIELD(f_mon_stmt_timestamp, nam_mon_timestamp, fld_timestamp_tz, 0, ODS_11_1) FIELD(f_mon_stmt_sql_text, nam_mon_sql_text, fld_source, 0, ODS_11_1) FIELD(f_mon_stmt_stat_id, nam_mon_stat_id, fld_stat_id, 0, ODS_11_1) FIELD(f_mon_stmt_expl_plan, nam_mon_expl_plan, fld_source, 0, ODS_11_1) @@ -562,7 +562,7 @@ RELATION(nam_mon_calls, rel_mon_calls, ODS_11_1, rel_virtual) FIELD(f_mon_call_caller_id, nam_mon_caller_id, fld_call_id, 0, ODS_11_1) FIELD(f_mon_call_name, nam_mon_obj_name, fld_gnr_name, 0, ODS_11_1) FIELD(f_mon_call_type, nam_mon_obj_type, fld_obj_type, 0, ODS_11_1) - FIELD(f_mon_call_timestamp, nam_mon_timestamp, fld_time, 0, ODS_11_1) + FIELD(f_mon_call_timestamp, nam_mon_timestamp, fld_timestamp_tz, 0, ODS_11_1) FIELD(f_mon_call_src_line, nam_mon_src_line, fld_src_info, 0, ODS_11_1) FIELD(f_mon_call_src_column, nam_mon_src_column, fld_src_info, 0, ODS_11_1) FIELD(f_mon_call_stat_id, nam_mon_stat_id, fld_stat_id, 0, ODS_11_1) diff --git a/src/jrd/req.h b/src/jrd/req.h index 71cbe16d5b..5c5ae72548 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -375,6 +375,14 @@ public: return Firebird::TimeZoneUtil::timeStampTzToTimeStamp(timeStampTz, req_attachment->att_current_timezone); } + + ISC_TIMESTAMP_TZ getTimeStampTz() const + { + ISC_TIMESTAMP_TZ timeStampTz; + timeStampTz.utc_timestamp = req_timestamp_utc.value(); + timeStampTz.time_zone = Firebird::TimeZoneUtil::GMT_ZONE; + return timeStampTz; + } }; // Flags for req_flags diff --git a/src/jrd/tra.h b/src/jrd/tra.h index cf0f7e40a0..291d22c6a9 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -175,7 +175,7 @@ public: tra_resources(*p), tra_context_vars(*p), tra_lock_timeout(DEFAULT_LOCK_TIMEOUT), - tra_timestamp(Firebird::TimeStamp::getCurrentTimeStamp()), + tra_timestamp(Firebird::TimeZoneUtil::getCurrentTimeStampUtc()), tra_stats(*p), tra_open_cursors(*p), tra_outer(outer), @@ -280,7 +280,7 @@ public: UCHAR tra_callback_count; // callback count for 'execute statement' SSHORT tra_lock_timeout; // in seconds, -1 means infinite, 0 means NOWAIT ULONG tra_next_blob_id; // ID of the previous blob or array created in this transaction - const Firebird::TimeStamp tra_timestamp; // transaction start time + const ISC_TIMESTAMP_TZ tra_timestamp; // transaction start time jrd_req* tra_requests; // Doubly linked list of requests active in this transaction MonitoringSnapshot* tra_mon_snapshot; // Database state snapshot (for monitoring purposes) RuntimeStatistics tra_stats; From e4226a60cfcf8dbc68aec24b295d6bf8e3a5c25f Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Tue, 27 Nov 2018 23:49:02 -0200 Subject: [PATCH 02/13] Rename fields and functions. --- src/common/TimeZoneUtil.cpp | 10 +++++----- src/common/TimeZoneUtil.h | 6 +++--- src/common/cvt.cpp | 6 +++--- src/common/cvt.h | 2 +- src/dsql/ExprNodes.cpp | 24 ++++++++++++------------ src/dsql/StmtNodes.cpp | 2 +- src/jrd/Attachment.cpp | 6 +++--- src/jrd/Database.h | 2 +- src/jrd/btr.cpp | 8 ++++---- src/jrd/cvt.cpp | 12 ++++++------ src/jrd/cvt_proto.h | 2 +- src/jrd/dfw.epp | 2 +- src/jrd/exe.cpp | 12 ++++++------ src/jrd/pag.cpp | 4 ++-- src/jrd/recsrc/ProcedureScan.cpp | 2 +- src/jrd/req.h | 6 +++--- src/jrd/tra.h | 2 +- 17 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index 4a5a53622d..c6904149e8 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -470,7 +470,7 @@ void TimeZoneUtil::localTimeToUtc(ISC_TIME& time, Callbacks* cb) void TimeZoneUtil::localTimeToUtc(ISC_TIME_TZ& timeTz, Callbacks* cb) { ISC_TIMESTAMP_TZ tempTimeStampTz; - tempTimeStampTz.utc_timestamp.timestamp_date = cb->getCurrentTimeStampUtc().timestamp_date; + tempTimeStampTz.utc_timestamp.timestamp_date = cb->getCurrentGmtTimeStamp().timestamp_date; tempTimeStampTz.utc_timestamp.timestamp_time = timeTz.utc_time; tempTimeStampTz.time_zone = timeTz.time_zone; localTimeStampToUtc(tempTimeStampTz); @@ -597,7 +597,7 @@ void TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, struct t TimeStamp::decode_timestamp(ts, times, fractions); } -ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentTimeStampUtc() +ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentSystemTimeStamp() { TimeStamp now = TimeStamp::getCurrentTimeStamp(); @@ -609,7 +609,7 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentTimeStampUtc() return tsTz; } -ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentTimeStampGmt() +ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentGmtTimeStamp() { //// TODO: Make this function does not depend on local time. TimeStamp now = TimeStamp::getCurrentTimeStamp(); @@ -624,10 +624,10 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentTimeStampGmt() return tsTz; } -void TimeZoneUtil::validateTimeStampUtc(NoThrowTimeStamp& ts) +void TimeZoneUtil::validateGmtTimeStamp(NoThrowTimeStamp& ts) { if (ts.isEmpty()) - ts.value() = getCurrentTimeStampUtc().utc_timestamp; + ts.value() = getCurrentGmtTimeStamp().utc_timestamp; } // Converts a time to timestamp-tz. diff --git a/src/common/TimeZoneUtil.h b/src/common/TimeZoneUtil.h index 2184dd1a05..ed36611ede 100644 --- a/src/common/TimeZoneUtil.h +++ b/src/common/TimeZoneUtil.h @@ -102,10 +102,10 @@ public: static void decodeTime(const ISC_TIME_TZ& timeTz, Callbacks* cb, struct tm* times, int* fractions = NULL); static void decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, struct tm* times, int* fractions = NULL); - static ISC_TIMESTAMP_TZ getCurrentTimeStampUtc(); - static ISC_TIMESTAMP_TZ getCurrentTimeStampGmt(); + static ISC_TIMESTAMP_TZ getCurrentSystemTimeStamp(); + static ISC_TIMESTAMP_TZ getCurrentGmtTimeStamp(); - static void validateTimeStampUtc(NoThrowTimeStamp& ts); + static void validateGmtTimeStamp(NoThrowTimeStamp& ts); static ISC_TIMESTAMP_TZ cvtTimeToTimeStampTz(const ISC_TIME& time, Callbacks* cb); static ISC_TIME_TZ cvtTimeToTimeTz(const ISC_TIME& time, Callbacks* cb); diff --git a/src/common/cvt.cpp b/src/common/cvt.cpp index 88a794fe32..862d81ea64 100644 --- a/src/common/cvt.cpp +++ b/src/common/cvt.cpp @@ -3377,7 +3377,7 @@ namespace virtual void validateLength(Jrd::CharSet* toCharset, SLONG toLength, const UCHAR* start, const USHORT to_size); virtual SLONG getLocalDate(); - virtual ISC_TIMESTAMP getCurrentTimeStampUtc(); + virtual ISC_TIMESTAMP getCurrentGmtTimeStamp(); virtual USHORT getSessionTimeZone(); virtual void isVersion4(bool& v4); } commonCallbacks(status_exception::raise); @@ -3411,9 +3411,9 @@ namespace return TimeStamp::getCurrentTimeStamp().value().timestamp_date; } - ISC_TIMESTAMP CommonCallbacks::getCurrentTimeStampUtc() + ISC_TIMESTAMP CommonCallbacks::getCurrentGmtTimeStamp() { - return TimeZoneUtil::timeStampTzToTimeStamp(TimeZoneUtil::getCurrentTimeStampUtc(), TimeZoneUtil::GMT_ZONE); + return TimeZoneUtil::timeStampTzToTimeStamp(TimeZoneUtil::getCurrentSystemTimeStamp(), TimeZoneUtil::GMT_ZONE); } USHORT CommonCallbacks::getSessionTimeZone() diff --git a/src/common/cvt.h b/src/common/cvt.h index 7d7491c54a..5c90e6f570 100644 --- a/src/common/cvt.h +++ b/src/common/cvt.h @@ -61,7 +61,7 @@ public: virtual void validateLength(Jrd::CharSet* toCharset, SLONG toLength, const UCHAR* start, const USHORT to_size) = 0; virtual SLONG getLocalDate() = 0; - virtual ISC_TIMESTAMP getCurrentTimeStampUtc() = 0; + virtual ISC_TIMESTAMP getCurrentGmtTimeStamp() = 0; virtual USHORT getSessionTimeZone() = 0; virtual void isVersion4(bool& v4) = 0; diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index 85236de947..91318d6772 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -4124,10 +4124,10 @@ dsc* CurrentDateNode::execute(thread_db* tdbb, jrd_req* request) const request->req_flags &= ~req_null; // Use the request timestamp. - fb_assert(!request->req_timestamp_utc.isEmpty()); + fb_assert(!request->req_gmt_timestamp.isEmpty()); ISC_TIMESTAMP_TZ timeStampTz; - timeStampTz.utc_timestamp = request->req_timestamp_utc.value(); + timeStampTz.utc_timestamp = request->req_gmt_timestamp.value(); timeStampTz.time_zone = TimeZoneUtil::GMT_ZONE; impure->vlu_misc.vlu_sql_date = TimeZoneUtil::timeStampTzToTimeStamp( @@ -4238,9 +4238,9 @@ dsc* CurrentTimeNode::execute(thread_db* tdbb, jrd_req* request) const request->req_flags &= ~req_null; // Use the request timestamp. - fb_assert(!request->req_timestamp_utc.isEmpty()); + fb_assert(!request->req_gmt_timestamp.isEmpty()); - ISC_TIME time = request->req_timestamp_utc.value().timestamp_time; + ISC_TIME time = request->req_gmt_timestamp.value().timestamp_time; TimeStamp::round_time(time, precision); impure->vlu_desc.dsc_dtype = dtype_sql_time_tz; @@ -4351,8 +4351,8 @@ dsc* CurrentTimeStampNode::execute(thread_db* tdbb, jrd_req* request) const request->req_flags &= ~req_null; // Use the request timestamp. - fb_assert(!request->req_timestamp_utc.isEmpty()); - ISC_TIMESTAMP encTimes = request->req_timestamp_utc.value(); + fb_assert(!request->req_gmt_timestamp.isEmpty()); + ISC_TIMESTAMP encTimes = request->req_gmt_timestamp.value(); memset(&impure->vlu_desc, 0, sizeof(impure->vlu_desc)); impure->vlu_desc.dsc_address = (UCHAR*) &impure->vlu_misc.vlu_timestamp_tz; @@ -7943,10 +7943,10 @@ dsc* LocalTimeNode::execute(thread_db* tdbb, jrd_req* request) const request->req_flags &= ~req_null; // Use the request timestamp. - fb_assert(!request->req_timestamp_utc.isEmpty()); + fb_assert(!request->req_gmt_timestamp.isEmpty()); ISC_TIMESTAMP_TZ timeStampTz; - timeStampTz.utc_timestamp = request->req_timestamp_utc.value(); + timeStampTz.utc_timestamp = request->req_gmt_timestamp.value(); timeStampTz.time_zone = TimeZoneUtil::GMT_ZONE; impure->vlu_misc.vlu_sql_time = TimeZoneUtil::timeStampTzToTimeStamp( @@ -8046,7 +8046,7 @@ dsc* LocalTimeStampNode::execute(thread_db* tdbb, jrd_req* request) const request->req_flags &= ~req_null; // Use the request timestamp. - fb_assert(!request->req_timestamp_utc.isEmpty()); + fb_assert(!request->req_gmt_timestamp.isEmpty()); impure->vlu_misc.vlu_timestamp = request->getLocalTimeStamp().value(); TimeStamp::round_time(impure->vlu_misc.vlu_timestamp.timestamp_time, precision); @@ -12807,7 +12807,7 @@ dsc* UdfCallNode::execute(thread_db* tdbb, jrd_req* request) const { Jrd::ContextPoolHolder context(tdbb, funcRequest->req_pool); // Save the old pool. - funcRequest->req_timestamp_utc = request->req_timestamp_utc; + funcRequest->req_gmt_timestamp = request->req_gmt_timestamp; EXE_start(tdbb, funcRequest, transaction); @@ -12836,7 +12836,7 @@ dsc* UdfCallNode::execute(thread_db* tdbb, jrd_req* request) const EXE_unwind(tdbb, funcRequest); funcRequest->req_attachment = NULL; funcRequest->req_flags &= ~(req_in_use | req_proc_fetch); - funcRequest->req_timestamp_utc.invalidate(); + funcRequest->req_gmt_timestamp.invalidate(); throw; } @@ -12864,7 +12864,7 @@ dsc* UdfCallNode::execute(thread_db* tdbb, jrd_req* request) const funcRequest->req_attachment = NULL; funcRequest->req_flags &= ~(req_in_use | req_proc_fetch); - funcRequest->req_timestamp_utc.invalidate(); + funcRequest->req_gmt_timestamp.invalidate(); } if (!(request->req_flags & req_null)) diff --git a/src/dsql/StmtNodes.cpp b/src/dsql/StmtNodes.cpp index d96a2f28b7..d6a1745663 100644 --- a/src/dsql/StmtNodes.cpp +++ b/src/dsql/StmtNodes.cpp @@ -3156,7 +3156,7 @@ void ExecProcedureNode::executeProcedure(thread_db* tdbb, jrd_req* request) cons try { - procRequest->req_timestamp_utc = request->req_timestamp_utc; + procRequest->req_gmt_timestamp = request->req_gmt_timestamp; EXE_start(tdbb, procRequest, transaction); diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index 7aed189b2d..add48a428f 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -212,7 +212,7 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb) att_base_stats(*pool), att_working_directory(*pool), att_filename(*pool), - att_timestamp(TimeZoneUtil::getCurrentTimeStampUtc()), + att_timestamp(TimeZoneUtil::getCurrentSystemTimeStamp()), att_context_vars(*pool), ddlTriggersContext(*pool), att_network_protocol(*pool), @@ -991,7 +991,7 @@ void Attachment::IdleTimer::handler() // If timer was reset to fire later, restart ITimer - const ISC_TIMESTAMP currentTimeGmt = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; + const ISC_TIMESTAMP currentTimeGmt = TimeZoneUtil::getCurrentGmtTimeStamp().utc_timestamp; const SINT64 curTime = currentTimeGmt.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + (SINT64) currentTimeGmt.timestamp_time; @@ -1028,7 +1028,7 @@ void Attachment::IdleTimer::reset(unsigned int timeout) return; } - const ISC_TIMESTAMP currentTimeGmt = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; + const ISC_TIMESTAMP currentTimeGmt = TimeZoneUtil::getCurrentGmtTimeStamp().utc_timestamp; const SINT64 curTime = currentTimeGmt.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + (SINT64) currentTimeGmt.timestamp_time; diff --git a/src/jrd/Database.h b/src/jrd/Database.h index 440898bf34..383be794e6 100644 --- a/src/jrd/Database.h +++ b/src/jrd/Database.h @@ -481,7 +481,7 @@ private: dbb_stats(*p), dbb_lock_owner_id(getLockOwnerId()), dbb_tip_cache(NULL), - dbb_creation_date(Firebird::TimeZoneUtil::getCurrentTimeStampGmt()), + dbb_creation_date(Firebird::TimeZoneUtil::getCurrentGmtTimeStamp()), dbb_external_file_directory_list(NULL), dbb_init_fini(FB_NEW_POOL(*getDefaultMemoryPool()) ExistenceRefMutex()), dbb_linger_seconds(0), diff --git a/src/jrd/btr.cpp b/src/jrd/btr.cpp index a6b018393f..8130dd717e 100644 --- a/src/jrd/btr.cpp +++ b/src/jrd/btr.cpp @@ -571,9 +571,9 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& Jrd::ContextPoolHolder context(tdbb, expr_request->req_pool); if (org_request) - expr_request->req_timestamp_utc = org_request->req_timestamp_utc; + expr_request->req_gmt_timestamp = org_request->req_gmt_timestamp; else - TimeZoneUtil::validateTimeStampUtc(expr_request->req_timestamp_utc); + TimeZoneUtil::validateGmtTimeStamp(expr_request->req_gmt_timestamp); if (!(result = EVL_expr(tdbb, expr_request, idx->idx_expression))) result = &idx->idx_expression_desc; @@ -587,7 +587,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& expr_request->req_caller = NULL; expr_request->req_flags &= ~req_in_use; - expr_request->req_timestamp_utc.invalidate(); + expr_request->req_gmt_timestamp.invalidate(); throw; } @@ -597,7 +597,7 @@ DSC* BTR_eval_expression(thread_db* tdbb, index_desc* idx, Record* record, bool& expr_request->req_caller = NULL; expr_request->req_flags &= ~req_in_use; - expr_request->req_timestamp_utc.invalidate(); + expr_request->req_gmt_timestamp.invalidate(); return result; } diff --git a/src/jrd/cvt.cpp b/src/jrd/cvt.cpp index 4858f485e2..0a9d2031ef 100644 --- a/src/jrd/cvt.cpp +++ b/src/jrd/cvt.cpp @@ -513,26 +513,26 @@ SLONG EngineCallbacks::getLocalDate() if (tdbb && (tdbb->getType() == ThreadData::tddDBB) && tdbb->getRequest()) { - fb_assert(!tdbb->getRequest()->req_timestamp_utc.isEmpty()); + fb_assert(!tdbb->getRequest()->req_gmt_timestamp.isEmpty()); return tdbb->getRequest()->getLocalTimeStamp().value().timestamp_date; } return TimeZoneUtil::timeStampTzToTimeStamp( - TimeZoneUtil::getCurrentTimeStampUtc(), getSessionTimeZone()).timestamp_date; + TimeZoneUtil::getCurrentSystemTimeStamp(), getSessionTimeZone()).timestamp_date; } -ISC_TIMESTAMP EngineCallbacks::getCurrentTimeStampUtc() +ISC_TIMESTAMP EngineCallbacks::getCurrentGmtTimeStamp() { thread_db* tdbb = JRD_get_thread_data(); if (tdbb && (tdbb->getType() == ThreadData::tddDBB) && tdbb->getRequest()) { - fb_assert(!tdbb->getRequest()->req_timestamp_utc.isEmpty()); - return tdbb->getRequest()->req_timestamp_utc.value(); + fb_assert(!tdbb->getRequest()->req_gmt_timestamp.isEmpty()); + return tdbb->getRequest()->req_gmt_timestamp.value(); } - return TimeZoneUtil::timeStampTzToTimeStamp(TimeZoneUtil::getCurrentTimeStampUtc(), TimeZoneUtil::GMT_ZONE); + return TimeZoneUtil::timeStampTzToTimeStamp(TimeZoneUtil::getCurrentSystemTimeStamp(), TimeZoneUtil::GMT_ZONE); } diff --git a/src/jrd/cvt_proto.h b/src/jrd/cvt_proto.h index f7874b8609..51c8513701 100644 --- a/src/jrd/cvt_proto.h +++ b/src/jrd/cvt_proto.h @@ -60,7 +60,7 @@ namespace Jrd virtual void validateLength(CharSet* toCharset, SLONG toLength, const UCHAR* start, const USHORT to_size); virtual SLONG getLocalDate(); - virtual ISC_TIMESTAMP getCurrentTimeStampUtc(); + virtual ISC_TIMESTAMP getCurrentGmtTimeStamp(); virtual USHORT getSessionTimeZone(); virtual void isVersion4(bool& v4); diff --git a/src/jrd/dfw.epp b/src/jrd/dfw.epp index 0facac2a7d..b1c917cdef 100644 --- a/src/jrd/dfw.epp +++ b/src/jrd/dfw.epp @@ -5888,7 +5888,7 @@ static bool make_version(thread_db* tdbb, SSHORT phase, DeferredWork* work, jrd_ AutoSetRestore2 autoRequest(tdbb, &thread_db::getRequest, &thread_db::setRequest, defaultRequest); - TimeZoneUtil::validateTimeStampUtc(defaultRequest->req_timestamp_utc); + TimeZoneUtil::validateGmtTimeStamp(defaultRequest->req_gmt_timestamp); TRA_attach_request(transaction, defaultRequest); dsc* result = EVL_expr(tdbb, defaultRequest, defaultNode); diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index 05bcda17d4..69eea04022 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -890,7 +890,7 @@ void EXE_start(thread_db* tdbb, jrd_req* request, jrd_tra* transaction) request->req_records_affected.clear(); // Store request start time for timestamp work - TimeZoneUtil::validateTimeStampUtc(request->req_timestamp_utc); + TimeZoneUtil::validateGmtTimeStamp(request->req_gmt_timestamp); // Set all invariants to not computed. const ULONG* const* ptr, * const* end; @@ -983,7 +983,7 @@ void EXE_unwind(thread_db* tdbb, jrd_req* request) request->req_flags &= ~(req_active | req_proc_fetch | req_reserved); request->req_flags |= req_abort | req_stall; - request->req_timestamp_utc.invalidate(); + request->req_gmt_timestamp.invalidate(); request->req_caller = NULL; request->req_proc_inputs = NULL; request->req_proc_caller = NULL; @@ -1106,9 +1106,9 @@ void EXE_execute_triggers(thread_db* tdbb, TimeStamp timestamp; if (request) - timestamp = request->req_timestamp_utc; + timestamp = request->req_gmt_timestamp; else - TimeZoneUtil::validateTimeStampUtc(timestamp); + TimeZoneUtil::validateGmtTimeStamp(timestamp); jrd_req* trigger = NULL; @@ -1154,7 +1154,7 @@ void EXE_execute_triggers(thread_db* tdbb, } } - trigger->req_timestamp_utc = timestamp; + trigger->req_gmt_timestamp = timestamp; trigger->req_trigger_action = trigger_action; TraceTrigExecute trace(tdbb, trigger, which_trig); @@ -1378,7 +1378,7 @@ const StmtNode* EXE_looper(thread_db* tdbb, jrd_req* request, const StmtNode* no TRA_release_request_snapshot(tdbb, request); request->req_flags &= ~(req_active | req_reserved); - request->req_timestamp_utc.invalidate(); + request->req_gmt_timestamp.invalidate(); release_blobs(tdbb, request); } diff --git a/src/jrd/pag.cpp b/src/jrd/pag.cpp index af3f2fbeb9..c567d45929 100644 --- a/src/jrd/pag.cpp +++ b/src/jrd/pag.cpp @@ -281,7 +281,7 @@ USHORT PAG_add_file(thread_db* tdbb, const TEXT* file_name, SLONG start) #ifdef SUPPORT_RAW_DEVICES // The following lines (taken from PAG_format_header) are needed to identify // this file in raw_devices_validate_database as a valid database attachment. - *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; + *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentGmtTimeStamp().utc_timestamp; // should we include milliseconds or not? //TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0); @@ -953,7 +953,7 @@ void PAG_format_header(thread_db* tdbb) WIN window(HEADER_PAGE_NUMBER); header_page* header = (header_page*) CCH_fake(tdbb, &window, 1); header->hdr_header.pag_scn = 0; - *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentTimeStampGmt().utc_timestamp; + *(ISC_TIMESTAMP*) header->hdr_creation_date = TimeZoneUtil::getCurrentGmtTimeStamp().utc_timestamp; // should we include milliseconds or not? //TimeStamp::round_time(header->hdr_creation_date->timestamp_time, 0); header->hdr_header.pag_type = pag_header; diff --git a/src/jrd/recsrc/ProcedureScan.cpp b/src/jrd/recsrc/ProcedureScan.cpp index cb8c8daa8f..1eab651903 100644 --- a/src/jrd/recsrc/ProcedureScan.cpp +++ b/src/jrd/recsrc/ProcedureScan.cpp @@ -106,7 +106,7 @@ void ProcedureScan::open(thread_db* tdbb) const try { - proc_request->req_timestamp_utc = request->req_timestamp_utc; + proc_request->req_gmt_timestamp = request->req_gmt_timestamp; TraceProcExecute trace(tdbb, proc_request, request, m_targetList); diff --git a/src/jrd/req.h b/src/jrd/req.h index 5c5ae72548..0d3236287d 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -266,7 +266,7 @@ public: ULONG req_flags; // misc request flags Savepoint* req_savepoints; // Looper savepoint list Savepoint* req_proc_sav_point; // procedure savepoint list - Firebird::TimeStamp req_timestamp_utc; // Start time of request + Firebird::TimeStamp req_gmt_timestamp; // Start time of request in GMT time zone unsigned int req_timeout; // query timeout in milliseconds, set by the dsql_req::setupTimer Firebird::RefPtr req_timer; // timeout timer, shared with dsql_req @@ -369,7 +369,7 @@ public: Firebird::TimeStamp getLocalTimeStamp() const { ISC_TIMESTAMP_TZ timeStampTz; - timeStampTz.utc_timestamp = req_timestamp_utc.value(); + timeStampTz.utc_timestamp = req_gmt_timestamp.value(); timeStampTz.time_zone = Firebird::TimeZoneUtil::GMT_ZONE; Firebird::TimeZoneUtil::localTimeStampToUtc(timeStampTz); @@ -379,7 +379,7 @@ public: ISC_TIMESTAMP_TZ getTimeStampTz() const { ISC_TIMESTAMP_TZ timeStampTz; - timeStampTz.utc_timestamp = req_timestamp_utc.value(); + timeStampTz.utc_timestamp = req_gmt_timestamp.value(); timeStampTz.time_zone = Firebird::TimeZoneUtil::GMT_ZONE; return timeStampTz; } diff --git a/src/jrd/tra.h b/src/jrd/tra.h index 291d22c6a9..e447bda6fe 100644 --- a/src/jrd/tra.h +++ b/src/jrd/tra.h @@ -175,7 +175,7 @@ public: tra_resources(*p), tra_context_vars(*p), tra_lock_timeout(DEFAULT_LOCK_TIMEOUT), - tra_timestamp(Firebird::TimeZoneUtil::getCurrentTimeStampUtc()), + tra_timestamp(Firebird::TimeZoneUtil::getCurrentSystemTimeStamp()), tra_stats(*p), tra_open_cursors(*p), tra_outer(outer), From 5ab4b98f7d34c186610d8d9098392bff3c30422e Mon Sep 17 00:00:00 2001 From: hvlad Date: Wed, 19 Dec 2018 11:42:03 +0200 Subject: [PATCH 03/13] Correct usage of different time units in IdleTimer --- src/jrd/Attachment.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/jrd/Attachment.cpp b/src/jrd/Attachment.cpp index add48a428f..7e1a121f6f 100644 --- a/src/jrd/Attachment.cpp +++ b/src/jrd/Attachment.cpp @@ -995,9 +995,9 @@ void Attachment::IdleTimer::handler() const SINT64 curTime = currentTimeGmt.timestamp_date * TimeStamp::ISC_TICKS_PER_DAY + (SINT64) currentTimeGmt.timestamp_time; - if (curTime < m_expTime) + if (curTime + ISC_TIME_SECONDS_PRECISION < m_expTime) { - reset(m_expTime - curTime); + reset((m_expTime - curTime) / ISC_TIME_SECONDS_PRECISION); return; } @@ -1021,6 +1021,8 @@ void Attachment::IdleTimer::reset(unsigned int timeout) { // Start timer if necessary. If timer was already started, don't restart // (or stop) it - handler() will take care about it. + // Take into account that timeout is in seconds while m_expTime is in ISC ticks + // and ITimerControl works with microseconds. if (!timeout) { @@ -1047,7 +1049,8 @@ void Attachment::IdleTimer::reset(unsigned int timeout) m_fireTime = 0; } - timerCtrl->start(&s, this, (m_expTime - curTime) * 100); + // Convert ISC ticks into microseconds + timerCtrl->start(&s, this, (m_expTime - curTime) * (1000 * 1000 / ISC_TIME_SECONDS_PRECISION)); check(&s); m_fireTime = m_expTime; } From 572c0675d6312551e5bbdf9e5b3e6d645dca60c7 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Mon, 24 Dec 2018 10:47:06 -0200 Subject: [PATCH 04/13] Refactor. --- src/common/TimeZoneUtil.cpp | 131 +++++++++++++++++++++--------------- src/common/unicode_util.cpp | 1 + src/common/unicode_util.h | 1 + 3 files changed, 79 insertions(+), 54 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index c6904149e8..3fe5e352a2 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -30,6 +30,7 @@ #include "firebird.h" #include "../common/TimeZoneUtil.h" #include "../common/StatusHolder.h" +#include "../common/classes/rwlock.h" #include "../common/classes/timestamp.h" #include "../common/classes/GenericMap.h" #include "unicode/ucal.h" @@ -69,8 +70,7 @@ namespace struct TimeZoneStartup { TimeZoneStartup(MemoryPool& pool) - : systemTimeZone(TimeZoneUtil::GMT_ZONE), - nameIdMap(pool) + : nameIdMap(pool) { #if defined DEV_BUILD && defined TZ_UPDATE tzUpdate(); @@ -82,55 +82,6 @@ namespace s.upper(); nameIdMap.put(s, i); } - - UErrorCode icuErrorCode = U_ZERO_ERROR; - - Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU(); - UCalendar* icuCalendar = icuLib.ucalOpen(NULL, -1, NULL, UCAL_GREGORIAN, &icuErrorCode); - - if (!icuCalendar) - { - gds__log("ICU's ucal_open error opening the default callendar."); - return; - } - - UChar buffer[TimeZoneUtil::MAX_SIZE]; - bool found = false; - - int32_t len = icuLib.ucalGetTimeZoneID(icuCalendar, buffer, FB_NELEM(buffer), &icuErrorCode); - - if (!U_FAILURE(icuErrorCode)) - { - bool error; - string bufferStrUnicode(reinterpret_cast(buffer), len * sizeof(USHORT)); - string bufferStrAscii(IntlUtil::convertUtf16ToAscii(bufferStrUnicode, &error)); - found = getId(bufferStrAscii, systemTimeZone); - } - else - icuErrorCode = U_ZERO_ERROR; - - if (found) - { - icuLib.ucalClose(icuCalendar); - return; - } - - gds__log("ICU error retrieving the system time zone: %d. Fallbacking to displacement.", int(icuErrorCode)); - - int32_t displacement = (icuLib.ucalGet(icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) + - icuLib.ucalGet(icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE; - - icuLib.ucalClose(icuCalendar); - - if (!U_FAILURE(icuErrorCode)) - { - int sign = displacement < 0 ? -1 : 1; - unsigned tzh = (unsigned) abs(int(displacement / 60)); - unsigned tzm = (unsigned) abs(int(displacement % 60)); - systemTimeZone = makeFromOffset(sign, tzh, tzm); - } - else - gds__log("Cannot retrieve the system time zone: %d.", int(icuErrorCode)); } bool getId(string name, USHORT& id) @@ -225,8 +176,6 @@ namespace } #endif // defined DEV_BUILD && defined TZ_UPDATE - USHORT systemTimeZone; - private: GenericMap > > nameIdMap; }; @@ -242,7 +191,81 @@ static InitInstance timeZoneStartup; // Return the current user's time zone. USHORT TimeZoneUtil::getSystemTimeZone() { - return timeZoneStartup().systemTimeZone; + static volatile bool cachedError = false; + static volatile USHORT cachedTimeZoneId = TimeZoneUtil::GMT_ZONE; + static volatile int32_t cachedTimeZoneNameLen = -1; + static UChar cachedTimeZoneName[TimeZoneUtil::MAX_SIZE]; + + if (cachedError) + return cachedTimeZoneId; + + UErrorCode icuErrorCode = U_ZERO_ERROR; + Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU(); + + UChar buffer[TimeZoneUtil::MAX_SIZE]; + int32_t len = icuLib.ucalGetDefaultTimeZone(buffer, FB_NELEM(buffer), &icuErrorCode); + + static GlobalPtr lock; + + ReadLockGuard readGuard(lock, "TimeZoneUtil::getSystemTimeZone"); + + if (!U_FAILURE(icuErrorCode) && + cachedTimeZoneNameLen != -1 && + len == cachedTimeZoneNameLen && + memcmp(buffer, cachedTimeZoneName, len * sizeof(USHORT)) == 0) + { + return cachedTimeZoneId; + } + + readGuard.release(); + WriteLockGuard writeGuard(lock, "TimeZoneUtil::getSystemTimeZone"); + + if (!U_FAILURE(icuErrorCode)) + { + bool error; + string bufferStrUnicode(reinterpret_cast(buffer), len * sizeof(USHORT)); + string bufferStrAscii(IntlUtil::convertUtf16ToAscii(bufferStrUnicode, &error)); + USHORT id; + + if (timeZoneStartup().getId(bufferStrAscii, id)) + { + memcpy(cachedTimeZoneName, buffer, len * sizeof(USHORT)); + cachedTimeZoneNameLen = len; + return (cachedTimeZoneId = id); + } + } + else + icuErrorCode = U_ZERO_ERROR; + + gds__log("ICU error retrieving the system time zone: %d. Fallbacking to displacement.", int(icuErrorCode)); + + UCalendar* icuCalendar = icuLib.ucalOpen(NULL, -1, NULL, UCAL_GREGORIAN, &icuErrorCode); + + if (!icuCalendar) + { + gds__log("ICU's ucal_open error opening the default callendar."); + cachedError = true; + return cachedTimeZoneId; // GMT + } + + int32_t displacement = (icuLib.ucalGet(icuCalendar, UCAL_ZONE_OFFSET, &icuErrorCode) + + icuLib.ucalGet(icuCalendar, UCAL_DST_OFFSET, &icuErrorCode)) / U_MILLIS_PER_MINUTE; + + icuLib.ucalClose(icuCalendar); + + if (!U_FAILURE(icuErrorCode)) + { + int sign = displacement < 0 ? -1 : 1; + unsigned tzh = (unsigned) abs(int(displacement / 60)); + unsigned tzm = (unsigned) abs(int(displacement % 60)); + cachedTimeZoneId = makeFromOffset(sign, tzh, tzm); + } + else + gds__log("Cannot retrieve the system time zone: %d.", int(icuErrorCode)); + + cachedError = true; + + return cachedTimeZoneId; } void TimeZoneUtil::getDatabaseVersion(Firebird::string& str) diff --git a/src/common/unicode_util.cpp b/src/common/unicode_util.cpp index fb9fd600d2..b06df0d2a2 100644 --- a/src/common/unicode_util.cpp +++ b/src/common/unicode_util.cpp @@ -285,6 +285,7 @@ private: return; getEntryPoint("ucal_getTZDataVersion", inModule, ucalGetTZDataVersion); + getEntryPoint("ucal_getDefaultTimeZone", inModule, ucalGetDefaultTimeZone); getEntryPoint("ucal_open", inModule, ucalOpen); getEntryPoint("ucal_close", inModule, ucalClose); getEntryPoint("ucal_setMillis", inModule, ucalSetMillis); diff --git a/src/common/unicode_util.h b/src/common/unicode_util.h index 92bc052398..644e7d3a78 100644 --- a/src/common/unicode_util.h +++ b/src/common/unicode_util.h @@ -124,6 +124,7 @@ public: int32_t (U_EXPORT2* ustrcmp) (const UChar* s1, const UChar* s2); const char* (U_EXPORT2* ucalGetTZDataVersion) (UErrorCode* status); + int32_t (U_EXPORT2* ucalGetDefaultTimeZone) (UChar* result, int32_t resultCapacity, UErrorCode* ec); UCalendar* (U_EXPORT2* ucalOpen) (const UChar* zoneID, int32_t len, const char* locale, UCalendarType type, UErrorCode* err); void (U_EXPORT2* ucalClose) (UCalendar* cal); From 4f446d506e7bb6f8f50738b043d5745c64d83055 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Mon, 24 Dec 2018 14:24:47 -0200 Subject: [PATCH 05/13] Message codes for time zone errors. --- lang_helpers/gds_codes.ftn | 6 ++++++ lang_helpers/gds_codes.pas | 6 ++++++ src/common/TimeZoneUtil.cpp | 14 +++++++++----- src/include/gen/codetext.h | 3 +++ src/include/gen/iberror.h | 10 ++++++++-- src/include/gen/msgs.h | 3 +++ src/include/gen/sql_code.h | 3 +++ src/include/gen/sql_state.h | 3 +++ src/msgs/facilities2.sql | 2 +- src/msgs/messages2.sql | 3 +++ src/msgs/system_errors2.sql | 3 +++ 11 files changed, 48 insertions(+), 8 deletions(-) diff --git a/lang_helpers/gds_codes.ftn b/lang_helpers/gds_codes.ftn index 7268453c4f..028ada30d2 100644 --- a/lang_helpers/gds_codes.ftn +++ b/lang_helpers/gds_codes.ftn @@ -1836,6 +1836,12 @@ C -- PARAMETER (GDS__parameter_name = 335545211) INTEGER*4 GDS__file_starting_page_err PARAMETER (GDS__file_starting_page_err = 335545212) + INTEGER*4 GDS__invalid_timezone_offset + PARAMETER (GDS__invalid_timezone_offset = 335545213) + INTEGER*4 GDS__invalid_timezone_region + PARAMETER (GDS__invalid_timezone_region = 335545214) + INTEGER*4 GDS__invalid_timezone_id + PARAMETER (GDS__invalid_timezone_id = 335545215) INTEGER*4 GDS__gfix_db_name PARAMETER (GDS__gfix_db_name = 335740929) INTEGER*4 GDS__gfix_invalid_sw diff --git a/lang_helpers/gds_codes.pas b/lang_helpers/gds_codes.pas index 6a38cc700c..db764b245f 100644 --- a/lang_helpers/gds_codes.pas +++ b/lang_helpers/gds_codes.pas @@ -1831,6 +1831,12 @@ const gds_parameter_name = 335545211; isc_file_starting_page_err = 335545212; gds_file_starting_page_err = 335545212; + isc_invalid_timezone_offset = 335545213; + gds_invalid_timezone_offset = 335545213; + isc_invalid_timezone_region = 335545214; + gds_invalid_timezone_region = 335545214; + isc_invalid_timezone_id = 335545215; + gds_invalid_timezone_id = 335545215; isc_gfix_db_name = 335740929; gds_gfix_db_name = 335740929; isc_gfix_invalid_sw = 335740930; diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index 3fe5e352a2..8a33258c4b 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -322,7 +322,7 @@ USHORT TimeZoneUtil::parse(const char* str, unsigned strLen) } if (p != end) - status_exception::raise(Arg::Gds(isc_random) << "Invalid time zone offset"); //// TODO: + status_exception::raise(Arg::Gds(isc_invalid_timezone_offset) << string(str, strLen)); return makeFromOffset(sign, tzh, tzm); } @@ -364,7 +364,7 @@ USHORT TimeZoneUtil::parseRegion(const char* str, unsigned strLen) return id; } - status_exception::raise(Arg::Gds(isc_random) << "Invalid time zone region"); //// TODO: + status_exception::raise(Arg::Gds(isc_invalid_timezone_region) << string(start, len)); return 0; } @@ -872,7 +872,7 @@ static const TimeZoneDesc* getDesc(USHORT timeZone) if (MAX_USHORT - timeZone < FB_NELEM(TIME_ZONE_LIST)) return &TIME_ZONE_LIST[MAX_USHORT - timeZone]; - status_exception::raise(Arg::Gds(isc_random) << "Invalid time zone id"); //// TODO: + status_exception::raise(Arg::Gds(isc_invalid_timezone_id) << Arg::Num(timeZone)); return nullptr; } @@ -886,7 +886,11 @@ static inline bool isOffset(USHORT timeZone) static USHORT makeFromOffset(int sign, unsigned tzh, unsigned tzm) { if (!TimeZoneUtil::isValidOffset(sign, tzh, tzm)) - status_exception::raise(Arg::Gds(isc_random) << "Invalid time zone offset"); //// TODO: + { + string str; + str.printf("%s%02u:%02u", (sign == -1 ? "-" : "+"), tzh, tzm); + status_exception::raise(Arg::Gds(isc_invalid_timezone_offset) << str); + } return (USHORT)((tzh * 60 + tzm) * sign + ONE_DAY); } @@ -909,7 +913,7 @@ static int parseNumber(const char*& p, const char* end) n = n * 10 + *p++ - '0'; if (p == start) - status_exception::raise(Arg::Gds(isc_random) << "Invalid time zone offset"); //// TODO: + status_exception::raise(Arg::Gds(isc_invalid_timezone_offset) << string(start, end - start)); return n; } diff --git a/src/include/gen/codetext.h b/src/include/gen/codetext.h index 15ab85256f..881d240847 100644 --- a/src/include/gen/codetext.h +++ b/src/include/gen/codetext.h @@ -914,6 +914,9 @@ static const struct { {"plugin_name", 335545210}, {"parameter_name", 335545211}, {"file_starting_page_err", 335545212}, + {"invalid_timezone_offset", 335545213}, + {"invalid_timezone_region", 335545214}, + {"invalid_timezone_id", 335545215}, {"gfix_db_name", 335740929}, {"gfix_invalid_sw", 335740930}, {"gfix_incmp_sw", 335740932}, diff --git a/src/include/gen/iberror.h b/src/include/gen/iberror.h index 5ffa687ab9..67fd1953f0 100644 --- a/src/include/gen/iberror.h +++ b/src/include/gen/iberror.h @@ -948,6 +948,9 @@ const ISC_STATUS isc_ses_reset_tran_rollback = 335545209L; const ISC_STATUS isc_plugin_name = 335545210L; const ISC_STATUS isc_parameter_name = 335545211L; const ISC_STATUS isc_file_starting_page_err = 335545212L; +const ISC_STATUS isc_invalid_timezone_offset = 335545213L; +const ISC_STATUS isc_invalid_timezone_region = 335545214L; +const ISC_STATUS isc_invalid_timezone_id = 335545215L; const ISC_STATUS isc_gfix_db_name = 335740929L; const ISC_STATUS isc_gfix_invalid_sw = 335740930L; const ISC_STATUS isc_gfix_incmp_sw = 335740932L; @@ -1422,7 +1425,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L; const ISC_STATUS isc_trace_switch_param_miss = 337182758L; const ISC_STATUS isc_trace_param_act_notcompat = 337182759L; const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L; -const ISC_STATUS isc_err_max = 1366; +const ISC_STATUS isc_err_max = 1369; #else /* c definitions */ @@ -2340,6 +2343,9 @@ const ISC_STATUS isc_err_max = 1366; #define isc_plugin_name 335545210L #define isc_parameter_name 335545211L #define isc_file_starting_page_err 335545212L +#define isc_invalid_timezone_offset 335545213L +#define isc_invalid_timezone_region 335545214L +#define isc_invalid_timezone_id 335545215L #define isc_gfix_db_name 335740929L #define isc_gfix_invalid_sw 335740930L #define isc_gfix_incmp_sw 335740932L @@ -2814,7 +2820,7 @@ const ISC_STATUS isc_err_max = 1366; #define isc_trace_switch_param_miss 337182758L #define isc_trace_param_act_notcompat 337182759L #define isc_trace_mandatory_switch_miss 337182760L -#define isc_err_max 1366 +#define isc_err_max 1369 #endif diff --git a/src/include/gen/msgs.h b/src/include/gen/msgs.h index 3140fc9e23..f9b893948d 100644 --- a/src/include/gen/msgs.h +++ b/src/include/gen/msgs.h @@ -917,6 +917,9 @@ Data source : @4"}, /* eds_statement */ {335545210, "Plugin @1:"}, /* plugin_name */ {335545211, "PARAMETER @1"}, /* parameter_name */ {335545212, "Starting page number for file @1 must be @2 or greater"}, /* file_starting_page_err */ + {335545213, "Invalid time zone offset: @1 - must be between -14:00 and +14:00"}, /* invalid_timezone_offset */ + {335545214, "Invalid time zone region: @1"}, /* invalid_timezone_region */ + {335545215, "Invalid time zone ID: @1"}, /* invalid_timezone_id */ {335740929, "data base file name (@1) already given"}, /* gfix_db_name */ {335740930, "invalid switch @1"}, /* gfix_invalid_sw */ {335740932, "incompatible switch combination"}, /* gfix_incmp_sw */ diff --git a/src/include/gen/sql_code.h b/src/include/gen/sql_code.h index 792f2a72b5..a577ea63da 100644 --- a/src/include/gen/sql_code.h +++ b/src/include/gen/sql_code.h @@ -913,6 +913,9 @@ static const struct { {335545210, -901}, /* 890 plugin_name */ {335545211, -901}, /* 891 parameter_name */ {335545212, -901}, /* 892 file_starting_page_err */ + {335545213, -901}, /* 893 invalid_timezone_offset */ + {335545214, -901}, /* 894 invalid_timezone_region */ + {335545215, -901}, /* 895 invalid_timezone_id */ {335740929, -901}, /* 1 gfix_db_name */ {335740930, -901}, /* 2 gfix_invalid_sw */ {335740932, -901}, /* 4 gfix_incmp_sw */ diff --git a/src/include/gen/sql_state.h b/src/include/gen/sql_state.h index 1e12fabdb3..010c05f4fc 100644 --- a/src/include/gen/sql_state.h +++ b/src/include/gen/sql_state.h @@ -913,6 +913,9 @@ static const struct { {335545210, "00000"}, // 890 plugin_name {335545211, "42000"}, // 891 parameter_name {335545212, "HY000"}, // 892 file_starting_page_err + {335545213, "22009"}, // 893 invalid_timezone_offset + {335545214, "22009"}, // 894 invalid_timezone_region + {335545215, "22009"}, // 895 invalid_timezone_id {335740929, "00000"}, // 1 gfix_db_name {335740930, "00000"}, // 2 gfix_invalid_sw {335740932, "00000"}, // 4 gfix_incmp_sw diff --git a/src/msgs/facilities2.sql b/src/msgs/facilities2.sql index f7a61fb410..029650a490 100644 --- a/src/msgs/facilities2.sql +++ b/src/msgs/facilities2.sql @@ -1,7 +1,7 @@ /* MAX_NUMBER is the next number to be used, always one more than the highest message number. */ set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?); -- -('2018-08-31 12:44:00', 'JRD', 0, 893) +('2018-12-24 14:22:00', 'JRD', 0, 896) ('2015-03-17 18:33:00', 'QLI', 1, 533) ('2015-01-07 18:01:51', 'GFIX', 3, 134) ('1996-11-07 13:39:40', 'GPRE', 4, 1) diff --git a/src/msgs/messages2.sql b/src/msgs/messages2.sql index 7dc77e640c..9c79cd7e7a 100644 --- a/src/msgs/messages2.sql +++ b/src/msgs/messages2.sql @@ -1000,6 +1000,9 @@ Data source : @4', NULL, NULL) ('plugin_name', NULL, 'CryptoManager.cpp', NULL, 0, 890, NULL, 'Plugin @1:', NULL, NULL); ('parameter_name', 'ProcedureManager::checkDependencies', 'dfw.e', NULL, 0, 891, NULL, 'PARAMETER @1', NULL, NULL); ('file_starting_page_err', 'add_file', 'dfw.epp', NULL, 0, 892, NULL, 'Starting page number for file @1 must be @2 or greater', NULL, NULL); +('invalid_timezone_offset', NULL, 'TimeZoneUtil.cpp', NULL, 0, 893, NULL, 'Invalid time zone offset: @1 - must be between -14:00 and +14:00', NULL, NULL); +('invalid_timezone_region', NULL, 'TimeZoneUtil.cpp', NULL, 0, 894, NULL, 'Invalid time zone region: @1', NULL, NULL); +('invalid_timezone_id', NULL, 'TimeZoneUtil.cpp', NULL, 0, 895, NULL, 'Invalid time zone ID: @1', NULL, NULL); -- QLI (NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL); (NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL); diff --git a/src/msgs/system_errors2.sql b/src/msgs/system_errors2.sql index 0340005b84..16fc27ca4e 100644 --- a/src/msgs/system_errors2.sql +++ b/src/msgs/system_errors2.sql @@ -899,6 +899,9 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA (-901, '00', '000', 0, 890, 'plugin_name', NULL, NULL) (-901, '42', '000', 0, 891, 'parameter_name', NULL, NULL) (-901, 'HY', '000', 0, 892, 'file_starting_page_err', NULL, NULL) +(-901, '22', '009', 0, 893, 'invalid_timezone_offset', NULL, NULL) +(-901, '22', '009', 0, 894, 'invalid_timezone_region', NULL, NULL) +(-901, '22', '009', 0, 895, 'invalid_timezone_id', NULL, NULL) -- GFIX (-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL) (-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL) From 3c6115a08cd79cc0517e0598f693ef7afb5d23a7 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Tue, 25 Dec 2018 11:02:19 -0200 Subject: [PATCH 06/13] Make TimeZoneUtil::getCurrentGmtTimeStamp() does not depend on the local time. --- src/common/TimeZoneUtil.cpp | 72 ++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 5 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index 8a33258c4b..c26996697f 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -634,14 +634,76 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentSystemTimeStamp() ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentGmtTimeStamp() { - //// TODO: Make this function does not depend on local time. - TimeStamp now = TimeStamp::getCurrentTimeStamp(); + NoThrowTimeStamp now; + + // ASF: This comment is copied from NoThrowTimeStamp::getCurrentTimeStamp. + // NS: We round generated timestamps to whole millisecond. + // Not many applications can deal with fractional milliseconds properly and + // we do not use high resolution timers either so actual time granularity + // is going to to be somewhere in range between 1 ms (like on UNIX/Risc) + // and 53 ms (such as Win9X) + + int milliseconds; + +#ifdef WIN_NT + FILETIME ftUtc; + SYSTEMTIME stUtc; + + GetSystemTimeAsFileTime(&ftUtc); + if (!FileTimeToSystemTime(&ftUtc, &stUtc)) + system_call_failed::raise("FileTimeToSystemTime"); + + milliseconds = stUtc.wMilliseconds; +#else + time_t seconds; // UTC time + +#ifdef HAVE_GETTIMEOFDAY + struct timeval tp; + GETTIMEOFDAY(&tp); + seconds = tp.tv_sec; + milliseconds = tp.tv_usec / 1000; +#else + struct timeb time_buffer; + ftime(&time_buffer); + seconds = time_buffer.time; + milliseconds = time_buffer.millitm; +#endif +#endif // WIN_NT + + const int fractions = milliseconds * ISC_TIME_SECONDS_PRECISION / 1000; + +#ifdef WIN_NT + // Manually convert SYSTEMTIME to "struct tm" used below + + struct tm times, *ptimes = × + + times.tm_sec = stLocal.wSecond; // seconds after the minute - [0,59] + times.tm_min = stLocal.wMinute; // minutes after the hour - [0,59] + times.tm_hour = stLocal.wHour; // hours since midnight - [0,23] + times.tm_mday = stLocal.wDay; // day of the month - [1,31] + times.tm_mon = stLocal.wMonth - 1; // months since January - [0,11] + times.tm_year = stLocal.wYear - 1900; // years since 1900 + times.tm_wday = stLocal.wDayOfWeek; // days since Sunday - [0,6] + + // --- no used for encoding below + times.tm_yday = 0; // days since January 1 - [0,365] + times.tm_isdst = -1; // daylight savings time flag +#else +#ifdef HAVE_GMTIME_R + struct tm times, *ptimes = × + if (!gmtime_r(&seconds, ×)) + system_call_failed::raise("gmtime_r"); +#else + struct tm *ptimes = gmtime(&seconds); + if (!ptimes) + system_call_failed::raise("gmtime"); +#endif +#endif // WIN_NT + + now.encode(ptimes, fractions); ISC_TIMESTAMP_TZ tsTz; tsTz.utc_timestamp = now.value(); - tsTz.time_zone = getSystemTimeZone(); - localTimeStampToUtc(tsTz); - tsTz.time_zone = GMT_ZONE; return tsTz; From 86081d3264f33b9154bf7e2a8011f6c0b042394f Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Thu, 27 Dec 2018 18:48:21 -0200 Subject: [PATCH 07/13] Better logging when some problem happened detecting the OS time zone. --- src/common/TimeZoneUtil.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index c26996697f..b30aa2df56 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -220,11 +220,13 @@ USHORT TimeZoneUtil::getSystemTimeZone() readGuard.release(); WriteLockGuard writeGuard(lock, "TimeZoneUtil::getSystemTimeZone"); + string bufferStrAscii; + if (!U_FAILURE(icuErrorCode)) { bool error; string bufferStrUnicode(reinterpret_cast(buffer), len * sizeof(USHORT)); - string bufferStrAscii(IntlUtil::convertUtf16ToAscii(bufferStrUnicode, &error)); + bufferStrAscii = IntlUtil::convertUtf16ToAscii(bufferStrUnicode, &error); USHORT id; if (timeZoneStartup().getId(bufferStrAscii, id)) @@ -237,7 +239,8 @@ USHORT TimeZoneUtil::getSystemTimeZone() else icuErrorCode = U_ZERO_ERROR; - gds__log("ICU error retrieving the system time zone: %d. Fallbacking to displacement.", int(icuErrorCode)); + gds__log("ICU error (%d) retrieving the system time zone (%s). Falling back to displacement.", + int(icuErrorCode), bufferStrAscii.c_str()); UCalendar* icuCalendar = icuLib.ucalOpen(NULL, -1, NULL, UCAL_GREGORIAN, &icuErrorCode); From 3ca18c540c0a2ea131a27daff6c8bc7ef6f0e31d Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Fri, 28 Dec 2018 15:38:50 -0200 Subject: [PATCH 08/13] Add config. parameter DefaultTimeZone. --- builds/install/misc/firebird.conf.in | 11 +++++++++++ doc/sql.extensions/README.time_zone.md | 2 +- src/common/TimeZoneUtil.cpp | 18 ++++++++++++++++-- src/common/config/config.cpp | 6 ++++++ src/common/config/config.h | 3 +++ 5 files changed, 37 insertions(+), 3 deletions(-) diff --git a/builds/install/misc/firebird.conf.in b/builds/install/misc/firebird.conf.in index 7ddbeed6b1..936a9ac16a 100644 --- a/builds/install/misc/firebird.conf.in +++ b/builds/install/misc/firebird.conf.in @@ -706,6 +706,17 @@ # #DummyPacketInterval = 0 +# +# Default session or client time zone. +# +# If empty, the default is the OS time zone. +# When set in the server, it defines the default session time zone for attachments. +# When set in the client, it defines the default time zone used with client-side API functions. +# +# Type: string +# +#DefaultTimeZone = + # ---------------------------- # TCP Protocol Settings diff --git a/doc/sql.extensions/README.time_zone.md b/doc/sql.extensions/README.time_zone.md index 8f2f0b278a..cffea1a339 100644 --- a/doc/sql.extensions/README.time_zone.md +++ b/doc/sql.extensions/README.time_zone.md @@ -4,7 +4,7 @@ Time zone support consists of `TIME WITH TIME ZONE` and `TIMESTAMP WITH TIME ZON The first important thing to understand is that `TIME WITHOUT TIME ZONE`, `TIMESTAMP WITHOUT TIME ZONE` and `DATE` data types are defined to use the session time zone when converting from or to a `TIME WITH TIME ZONE` or `TIMESTAMP WITH TIME ZONE`. `TIME` and `TIMESTAMP` are synonymous to theirs respectively `WITHOUT TIME ZONE` data types. -The session time zone, as the name implies, can be a different one for each database attachment. It can be set with the isc_dpb_session_time_zone DPB, and if not, it starts by default defined to be the same time zone used by the Firebird database OS process. +The session time zone, as the name implies, can be a different one for each database attachment. It can be set with the isc_dpb_session_time_zone DPB, and if not, it starts by default defined to be the `firebird.conf` parameter `DefaultTimeZone` or the same time zone used by the Firebird OS process when the parameter is not defined. A change in `DefaultTimeZone` configuration or the OS time zone does not changes the default of a running Firebird process. It can then be changed with `SET TIME ZONE` statement to a given time zone or reset to its original value with `SET TIME ZONE LOCAL`. diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index b30aa2df56..b390fec2ca 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -33,6 +33,7 @@ #include "../common/classes/rwlock.h" #include "../common/classes/timestamp.h" #include "../common/classes/GenericMap.h" +#include "../common/config/config.h" #include "unicode/ucal.h" #ifdef TZ_UPDATE @@ -195,6 +196,7 @@ USHORT TimeZoneUtil::getSystemTimeZone() static volatile USHORT cachedTimeZoneId = TimeZoneUtil::GMT_ZONE; static volatile int32_t cachedTimeZoneNameLen = -1; static UChar cachedTimeZoneName[TimeZoneUtil::MAX_SIZE]; + static GlobalPtr lock; if (cachedError) return cachedTimeZoneId; @@ -203,9 +205,21 @@ USHORT TimeZoneUtil::getSystemTimeZone() Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU(); UChar buffer[TimeZoneUtil::MAX_SIZE]; - int32_t len = icuLib.ucalGetDefaultTimeZone(buffer, FB_NELEM(buffer), &icuErrorCode); + int32_t len; + const char* configDefault = Config::getDefaultTimeZone(); - static GlobalPtr lock; + if (configDefault && configDefault[0]) + { + UChar* dst = buffer; + + for (const char* src = configDefault; src - configDefault < TimeZoneUtil::MAX_SIZE && *src; ++src, ++dst) + *dst = *src; + + *dst = 0; + len = dst - buffer; + } + else + len = icuLib.ucalGetDefaultTimeZone(buffer, FB_NELEM(buffer), &icuErrorCode); ReadLockGuard readGuard(lock, "TimeZoneUtil::getSystemTimeZone"); diff --git a/src/common/config/config.cpp b/src/common/config/config.cpp index f1beef35bb..b51520d349 100644 --- a/src/common/config/config.cpp +++ b/src/common/config/config.cpp @@ -151,6 +151,7 @@ const Config::ConfigEntry Config::entries[MAX_CONFIG_KEY] = {TYPE_INTEGER, "DefaultDbCachePages", (ConfigValue) -1}, // pages {TYPE_INTEGER, "ConnectionTimeout", (ConfigValue) 180}, // seconds {TYPE_INTEGER, "DummyPacketInterval", (ConfigValue) 0}, // seconds + {TYPE_STRING, "DefaultTimeZone", (ConfigValue) ""}, {TYPE_INTEGER, "LockMemSize", (ConfigValue) 1048576}, // bytes {TYPE_INTEGER, "LockHashSlots", (ConfigValue) 8191}, // slots {TYPE_INTEGER, "LockAcquireSpins", (ConfigValue) 0}, @@ -517,6 +518,11 @@ int Config::getDummyPacketInterval() const return get(KEY_DUMMY_PACKET_INTERVAL); } +const char* Config::getDefaultTimeZone() +{ + return getDefaultConfig()->get(KEY_DEFAULT_TIME_ZONE); +} + int Config::getLockMemSize() const { int size = get(KEY_LOCK_MEM_SIZE); diff --git a/src/common/config/config.h b/src/common/config/config.h index 9ceea434cd..530d186560 100644 --- a/src/common/config/config.h +++ b/src/common/config/config.h @@ -98,6 +98,7 @@ public: KEY_DEFAULT_DB_CACHE_PAGES, KEY_CONNECTION_TIMEOUT, KEY_DUMMY_PACKET_INTERVAL, + KEY_DEFAULT_TIME_ZONE, KEY_LOCK_MEM_SIZE, KEY_LOCK_HASH_SLOTS, KEY_LOCK_ACQUIRE_SPINS, @@ -263,6 +264,8 @@ public: // Dummy packet interval int getDummyPacketInterval() const; + static const char* getDefaultTimeZone(); + // Lock manager memory size int getLockMemSize() const; From 647d06cde597cadd528d2a6d71db0a91ed5b8f5c Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Fri, 28 Dec 2018 15:51:51 -0200 Subject: [PATCH 09/13] Make code faster. --- src/common/TimeZoneUtil.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index b390fec2ca..3526795fbb 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -201,6 +201,11 @@ USHORT TimeZoneUtil::getSystemTimeZone() if (cachedError) return cachedTimeZoneId; + // ASF: The code below in this function is prepared to detect changes in OS time zone or config setting, but + // the called functions are not. So cache and return directly the previously detected time zone. + if (cachedTimeZoneNameLen != -1) + return cachedTimeZoneId; + UErrorCode icuErrorCode = U_ZERO_ERROR; Jrd::UnicodeUtil::ConversionICU& icuLib = Jrd::UnicodeUtil::getConversionICU(); @@ -246,8 +251,9 @@ USHORT TimeZoneUtil::getSystemTimeZone() if (timeZoneStartup().getId(bufferStrAscii, id)) { memcpy(cachedTimeZoneName, buffer, len * sizeof(USHORT)); + cachedTimeZoneId = id; cachedTimeZoneNameLen = len; - return (cachedTimeZoneId = id); + return cachedTimeZoneId; } } else From b4caf53cc8d7391e6e7c71d474ae9e7f5dc0e4a6 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Fri, 28 Dec 2018 21:51:02 -0200 Subject: [PATCH 10/13] Simplify the Windows code - untested. --- src/common/TimeZoneUtil.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index 3526795fbb..db9382275d 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -669,13 +669,8 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentGmtTimeStamp() int milliseconds; #ifdef WIN_NT - FILETIME ftUtc; SYSTEMTIME stUtc; - - GetSystemTimeAsFileTime(&ftUtc); - if (!FileTimeToSystemTime(&ftUtc, &stUtc)) - system_call_failed::raise("FileTimeToSystemTime"); - + GetSystemTime(&stUtc); milliseconds = stUtc.wMilliseconds; #else time_t seconds; // UTC time From e7804a1abeb3561067bad0de01bc0bff57e78b33 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Fri, 28 Dec 2018 21:55:59 -0200 Subject: [PATCH 11/13] Fix (try) Windows build. --- src/common/TimeZoneUtil.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index db9382275d..516b6cf7d1 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -695,13 +695,13 @@ ISC_TIMESTAMP_TZ TimeZoneUtil::getCurrentGmtTimeStamp() struct tm times, *ptimes = × - times.tm_sec = stLocal.wSecond; // seconds after the minute - [0,59] - times.tm_min = stLocal.wMinute; // minutes after the hour - [0,59] - times.tm_hour = stLocal.wHour; // hours since midnight - [0,23] - times.tm_mday = stLocal.wDay; // day of the month - [1,31] - times.tm_mon = stLocal.wMonth - 1; // months since January - [0,11] - times.tm_year = stLocal.wYear - 1900; // years since 1900 - times.tm_wday = stLocal.wDayOfWeek; // days since Sunday - [0,6] + times.tm_sec = stUtc.wSecond; // seconds after the minute - [0,59] + times.tm_min = stUtc.wMinute; // minutes after the hour - [0,59] + times.tm_hour = stUtc.wHour; // hours since midnight - [0,23] + times.tm_mday = stUtc.wDay; // day of the month - [1,31] + times.tm_mon = stUtc.wMonth - 1; // months since January - [0,11] + times.tm_year = stUtc.wYear - 1900; // years since 1900 + times.tm_wday = stUtc.wDayOfWeek; // days since Sunday - [0,6] // --- no used for encoding below times.tm_yday = 0; // days since January 1 - [0,365] From 54df72afca87e30470ba9be76828402f469f7938 Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Sat, 29 Dec 2018 15:24:24 -0200 Subject: [PATCH 12/13] Make sessions dump their data using their own time zones. --- src/jrd/req.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jrd/req.h b/src/jrd/req.h index 0d3236287d..a779a0dca6 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -380,7 +380,7 @@ public: { ISC_TIMESTAMP_TZ timeStampTz; timeStampTz.utc_timestamp = req_gmt_timestamp.value(); - timeStampTz.time_zone = Firebird::TimeZoneUtil::GMT_ZONE; + timeStampTz.time_zone = req_attachment->att_current_timezone; return timeStampTz; } }; From e3e8d872ec687c5119bb136393afc56fed111b4a Mon Sep 17 00:00:00 2001 From: Adriano dos Santos Fernandes Date: Sat, 29 Dec 2018 15:36:56 -0200 Subject: [PATCH 13/13] Optimizations. --- src/common/TimeZoneUtil.cpp | 12 +++++++++--- src/jrd/req.h | 1 - 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/common/TimeZoneUtil.cpp b/src/common/TimeZoneUtil.cpp index 516b6cf7d1..e8dc7a1373 100644 --- a/src/common/TimeZoneUtil.cpp +++ b/src/common/TimeZoneUtil.cpp @@ -429,7 +429,9 @@ void TimeZoneUtil::extractOffset(const ISC_TIMESTAMP_TZ& timeStampTz, int* sign, { SSHORT displacement; - if (isOffset(timeStampTz.time_zone)) + if (timeStampTz.time_zone == GMT_ZONE) + displacement = 0; + else if (isOffset(timeStampTz.time_zone)) displacement = offsetZoneToDisplacement(timeStampTz.time_zone); else { @@ -543,7 +545,9 @@ void TimeZoneUtil::localTimeStampToUtc(ISC_TIMESTAMP_TZ& timeStampTz) { int displacement; - if (isOffset(timeStampTz.time_zone)) + if (timeStampTz.time_zone == GMT_ZONE) + return; + else if (isOffset(timeStampTz.time_zone)) displacement = offsetZoneToDisplacement(timeStampTz.time_zone); else { @@ -600,7 +604,9 @@ void TimeZoneUtil::decodeTimeStamp(const ISC_TIMESTAMP_TZ& timeStampTz, struct t timeStampTz.utc_timestamp.timestamp_time; int displacement; - if (isOffset(timeStampTz.time_zone)) + if (timeStampTz.time_zone == GMT_ZONE) + displacement = 0; + else if (isOffset(timeStampTz.time_zone)) displacement = offsetZoneToDisplacement(timeStampTz.time_zone); else { diff --git a/src/jrd/req.h b/src/jrd/req.h index a779a0dca6..d88ca0b593 100644 --- a/src/jrd/req.h +++ b/src/jrd/req.h @@ -371,7 +371,6 @@ public: ISC_TIMESTAMP_TZ timeStampTz; timeStampTz.utc_timestamp = req_gmt_timestamp.value(); timeStampTz.time_zone = Firebird::TimeZoneUtil::GMT_ZONE; - Firebird::TimeZoneUtil::localTimeStampToUtc(timeStampTz); return Firebird::TimeZoneUtil::timeStampTzToTimeStamp(timeStampTz, req_attachment->att_current_timezone); }