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

Improvement CORE-5853 - Forward-compatible expressions LOCALTIME and LOCALTIMESTAMP.

This commit is contained in:
Adriano dos Santos Fernandes 2018-06-20 12:56:31 -03:00 committed by Adriano dos Santos Fernandes
parent 4bac379c1a
commit 15e25b3c35
7 changed files with 84 additions and 10 deletions

View File

@ -0,0 +1,13 @@
# Time Zone support forward compatibility
In version 4.0, Firebird will support time zones.
Within this support will come an incompatibility with previous versions' `CURRENT_TIME` and `CURRENT_TIMESTAMP` expressions.
In v4, `CURRENT_TIME` and `CURRENT_TIMESTAMP` will respectively return expressions of data type `TIME WITH TIME ZONE` and `TIMESTAMP WITH TIME ZONE`.
To make your queries and database code compatible with future versions, from v3.0.4 you can instead use `LOCALTIME` and `LOCALTIMESTAMP`. In v3, these `LOCAL*` expressions will work indenticaly to their correspondents `CURRENT_*` expressions.
In v4, `LOCAL*` expressions will continue to work identically as now, but the `CURRENT_*` expressions will change.
You should not start using `LOCALTIME` and `LOCALTIMESTAMP` if your database may be downgraded to v3.0.3 or another version, as the old versions will not recognize the new expressions.

View File

@ -3460,14 +3460,15 @@ dsc* CurrentDateNode::execute(thread_db* /*tdbb*/, jrd_req* request) const
static RegisterNode<CurrentTimeNode> regCurrentTimeNode(blr_current_time);
static RegisterNode<CurrentTimeNode> regCurrentTimeNode2(blr_current_time2);
static RegisterNode<CurrentTimeNode> regCurrentTimeNode3(blr_local_time);
DmlNode* CurrentTimeNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp)
{
unsigned precision = DEFAULT_TIME_PRECISION;
fb_assert(blrOp == blr_current_time || blrOp == blr_current_time2);
fb_assert(blrOp == blr_current_time || blrOp == blr_current_time2 || blrOp == blr_local_time);
if (blrOp == blr_current_time2)
if (blrOp == blr_current_time2 || blrOp == blr_local_time)
{
precision = csb->csb_blr_reader.getByte();
@ -3489,12 +3490,17 @@ string CurrentTimeNode::internalPrint(NodePrinter& printer) const
void CurrentTimeNode::setParameterName(dsql_par* parameter) const
{
parameter->par_name = parameter->par_alias = "CURRENT_TIME";
parameter->par_name = parameter->par_alias = dsqlLocal ? "LOCALTIME" : "CURRENT_TIME";
}
void CurrentTimeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
if (precision == DEFAULT_TIME_PRECISION)
if (dsqlLocal)
{
dsqlScratch->appendUChar(blr_local_time);
dsqlScratch->appendUChar(precision);
}
else if (precision == DEFAULT_TIME_PRECISION)
dsqlScratch->appendUChar(blr_current_time);
else
{
@ -3572,15 +3578,16 @@ dsc* CurrentTimeNode::execute(thread_db* /*tdbb*/, jrd_req* request) const
static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode(blr_current_timestamp);
static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode2(blr_current_timestamp2);
static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode3(blr_local_timestamp);
DmlNode* CurrentTimeStampNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerScratch* csb,
const UCHAR blrOp)
{
unsigned precision = DEFAULT_TIMESTAMP_PRECISION;
fb_assert(blrOp == blr_current_timestamp || blrOp == blr_current_timestamp2);
fb_assert(blrOp == blr_current_timestamp || blrOp == blr_current_timestamp2 || blrOp == blr_local_timestamp);
if (blrOp == blr_current_timestamp2)
if (blrOp == blr_current_timestamp2 || blrOp == blr_local_timestamp)
{
precision = csb->csb_blr_reader.getByte();
@ -3602,12 +3609,17 @@ string CurrentTimeStampNode::internalPrint(NodePrinter& printer) const
void CurrentTimeStampNode::setParameterName(dsql_par* parameter) const
{
parameter->par_name = parameter->par_alias = "CURRENT_TIMESTAMP";
parameter->par_name = parameter->par_alias = dsqlLocal ? "LOCALTIMESTAMP" : "CURRENT_TIMESTAMP";
}
void CurrentTimeStampNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{
if (precision == DEFAULT_TIMESTAMP_PRECISION)
if (dsqlLocal)
{
dsqlScratch->appendUChar(blr_local_timestamp);
dsqlScratch->appendUChar(precision);
}
else if (precision == DEFAULT_TIMESTAMP_PRECISION)
dsqlScratch->appendUChar(blr_current_timestamp);
else
{

View File

@ -340,7 +340,8 @@ class CurrentTimeNode : public TypedNode<ValueExprNode, ExprNode::TYPE_CURRENT_T
public:
CurrentTimeNode(MemoryPool& pool, unsigned aPrecision)
: TypedNode<ValueExprNode, ExprNode::TYPE_CURRENT_TIME>(pool),
precision(aPrecision)
precision(aPrecision),
dsqlLocal(false)
{
}
@ -359,6 +360,7 @@ public:
public:
unsigned precision;
bool dsqlLocal;
};
@ -367,7 +369,8 @@ class CurrentTimeStampNode : public TypedNode<ValueExprNode, ExprNode::TYPE_CURR
public:
CurrentTimeStampNode(MemoryPool& pool, unsigned aPrecision)
: TypedNode<ValueExprNode, ExprNode::TYPE_CURRENT_TIMESTAMP>(pool),
precision(aPrecision)
precision(aPrecision),
dsqlLocal(false)
{
}
@ -386,6 +389,7 @@ public:
public:
unsigned precision;
bool dsqlLocal;
};

View File

@ -589,6 +589,11 @@ using namespace Firebird;
%token <metaNamePtr> REGR_SXY
%token <metaNamePtr> REGR_SYY
// tokens added for Firebird 3.0.4
%token <metaNamePtr> LOCALTIME
%token <metaNamePtr> LOCALTIMESTAMP
// precedence declarations for expression evaluation
%left OR
@ -3863,6 +3868,8 @@ keyword_or_column
| UPDATING
| VAR_SAMP
| VAR_POP
| LOCALTIME // added in FB 3.0.4
| LOCALTIMESTAMP
;
col_opt
@ -6575,8 +6582,34 @@ datetime_value_expression
$$ = newNode<CurrentTimeNode>($2);
}
| LOCALTIME time_precision_opt
{
if (client_dialect < SQL_DIALECT_V6_TRANSITION)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
Arg::Gds(isc_sql_dialect_datatype_unsupport) << Arg::Num(client_dialect) <<
Arg::Str("TIME"));
}
if (db_dialect < SQL_DIALECT_V6_TRANSITION)
{
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
Arg::Gds(isc_sql_db_dialect_dtype_unsupport) << Arg::Num(db_dialect) <<
Arg::Str("TIME"));
}
CurrentTimeNode* node = newNode<CurrentTimeNode>($2);
node->dsqlLocal = true;
$$ = node;
}
| CURRENT_TIMESTAMP timestamp_precision_opt
{ $$ = newNode<CurrentTimeStampNode>($2); }
| LOCALTIMESTAMP timestamp_precision_opt
{
CurrentTimeStampNode* node = newNode<CurrentTimeStampNode>($2);
node->dsqlLocal = true;
$$ = node;
}
;
%type <uintVal> time_precision_opt

View File

@ -241,5 +241,10 @@ static const struct
{"subfunc", function},
{"record_version2", byte_line},
{"gen_id2", gen_id2}, // 210
{0, 0},
{0, 0},
{0, 0},
{"local_timestamp", byte_line},
{"local_time", byte_line},
{0, 0}
};

View File

@ -407,4 +407,9 @@
#define blr_record_version2 (unsigned char) 209
#define blr_gen_id2 (unsigned char) 210 // NEXT VALUE FOR generator
// FB 3.0.4 specific BLR
#define blr_local_timestamp (unsigned char) 214
#define blr_local_time (unsigned char) 215
#endif // JRD_BLR_H

View File

@ -250,6 +250,8 @@ static const TOK tokens[] =
{LINGER, "LINGER", 2, true},
{LIST, "LIST", 2, false},
{LN, "LN", 2, false},
{LOCALTIME, "LOCALTIME", 2, true},
{LOCALTIMESTAMP, "LOCALTIMESTAMP", 2, true},
{LOCK, "LOCK", 2, true},
{LOG, "LOG", 2, false},
{LOG10, "LOG10", 2, false},