"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/dsql/ExprNodes.cpp" between
Firebird-3.0.2.32703-0.tar.bz2 and Firebird-3.0.4.33054-0.tar.bz2

About: Firebird is a relational database offering many ANSI SQL standard features.

ExprNodes.cpp  (Firebird-3.0.2.32703-0.tar.bz2):ExprNodes.cpp  (Firebird-3.0.4.33054-0.tar.bz2)
skipping to change at line 2864 skipping to change at line 2864
impure->vlu_desc.dsc_address = string->str_data; impure->vlu_desc.dsc_address = string->str_data;
} }
EVL_validate(tdbb, Item(Item::TYPE_CAST), itemInfo, EVL_validate(tdbb, Item(Item::TYPE_CAST), itemInfo,
value, value == NULL || (value->dsc_flags & DSC_null)); value, value == NULL || (value->dsc_flags & DSC_null));
if (!value) if (!value)
return NULL; return NULL;
if (DTYPE_IS_BLOB(value->dsc_dtype) || DTYPE_IS_BLOB(impure->vlu_desc.dsc _dtype)) if (DTYPE_IS_BLOB(value->dsc_dtype) || DTYPE_IS_BLOB(impure->vlu_desc.dsc _dtype))
blb::move(tdbb, value, &impure->vlu_desc, NULL); blb::move(tdbb, value, &impure->vlu_desc);
else else
MOV_move(tdbb, value, &impure->vlu_desc); MOV_move(tdbb, value, &impure->vlu_desc);
if (impure->vlu_desc.dsc_dtype == dtype_text) if (impure->vlu_desc.dsc_dtype == dtype_text)
INTL_adjust_text_descriptor(tdbb, &impure->vlu_desc); INTL_adjust_text_descriptor(tdbb, &impure->vlu_desc);
return &impure->vlu_desc; return &impure->vlu_desc;
} }
//-------------------- //--------------------
skipping to change at line 3429 skipping to change at line 3429
impure->vlu_desc.dsc_length = type_lengths[dtype_sql_date]; impure->vlu_desc.dsc_length = type_lengths[dtype_sql_date];
*(ULONG*) impure->vlu_desc.dsc_address = encTimes.timestamp_date; *(ULONG*) impure->vlu_desc.dsc_address = encTimes.timestamp_date;
return &impure->vlu_desc; return &impure->vlu_desc;
} }
//-------------------- //--------------------
static RegisterNode<CurrentTimeNode> regCurrentTimeNode(blr_current_time); static RegisterNode<CurrentTimeNode> regCurrentTimeNode(blr_current_time);
static RegisterNode<CurrentTimeNode> regCurrentTimeNode2(blr_current_time2); static RegisterNode<CurrentTimeNode> regCurrentTimeNode2(blr_current_time2);
static RegisterNode<CurrentTimeNode> regCurrentTimeNode3(blr_local_time);
DmlNode* CurrentTimeNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerS cratch* csb, const UCHAR blrOp) DmlNode* CurrentTimeNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, CompilerS cratch* csb, const UCHAR blrOp)
{ {
unsigned precision = DEFAULT_TIME_PRECISION; 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 || blrO p == blr_local_time);
if (blrOp == blr_current_time2) if (blrOp == blr_current_time2 || blrOp == blr_local_time)
{ {
precision = csb->csb_blr_reader.getByte(); precision = csb->csb_blr_reader.getByte();
if (precision > MAX_TIME_PRECISION) if (precision > MAX_TIME_PRECISION)
ERR_post(Arg::Gds(isc_invalid_time_precision) << Arg::Num (MAX_TIME_PRECISION)); ERR_post(Arg::Gds(isc_invalid_time_precision) << Arg::Num (MAX_TIME_PRECISION));
} }
return FB_NEW_POOL(pool) CurrentTimeNode(pool, precision); return FB_NEW_POOL(pool) CurrentTimeNode(pool, precision);
} }
skipping to change at line 3458 skipping to change at line 3459
{ {
ValueExprNode::internalPrint(printer); ValueExprNode::internalPrint(printer);
NODE_PRINT(printer, precision); NODE_PRINT(printer, precision);
return "CurrentTimeNode"; return "CurrentTimeNode";
} }
void CurrentTimeNode::setParameterName(dsql_par* parameter) const void CurrentTimeNode::setParameterName(dsql_par* parameter) const
{ {
parameter->par_name = parameter->par_alias = "CURRENT_TIME"; parameter->par_name = parameter->par_alias = dsqlLocal ? "LOCALTIME" : "C URRENT_TIME";
} }
void CurrentTimeNode::genBlr(DsqlCompilerScratch* dsqlScratch) 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); dsqlScratch->appendUChar(blr_current_time);
else else
{ {
dsqlScratch->appendUChar(blr_current_time2); dsqlScratch->appendUChar(blr_current_time2);
dsqlScratch->appendUChar(precision); dsqlScratch->appendUChar(precision);
} }
} }
void CurrentTimeNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc) void CurrentTimeNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
{ {
skipping to change at line 3539 skipping to change at line 3545
impure->vlu_desc.dsc_length = type_lengths[dtype_sql_time]; impure->vlu_desc.dsc_length = type_lengths[dtype_sql_time];
*(ULONG*) impure->vlu_desc.dsc_address = encTimes.timestamp_time; *(ULONG*) impure->vlu_desc.dsc_address = encTimes.timestamp_time;
return &impure->vlu_desc; return &impure->vlu_desc;
} }
//-------------------- //--------------------
static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode(blr_current_ti mestamp); static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode(blr_current_ti mestamp);
static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode2(blr_current_t imestamp2); static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode2(blr_current_t imestamp2);
static RegisterNode<CurrentTimeStampNode> regCurrentTimeStampNode3(blr_local_tim estamp);
DmlNode* CurrentTimeStampNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, Comp ilerScratch* csb, DmlNode* CurrentTimeStampNode::parse(thread_db* /*tdbb*/, MemoryPool& pool, Comp ilerScratch* csb,
const UCHAR blrOp) const UCHAR blrOp)
{ {
unsigned precision = DEFAULT_TIMESTAMP_PRECISION; unsigned precision = DEFAULT_TIMESTAMP_PRECISION;
fb_assert(blrOp == blr_current_timestamp || blrOp == blr_current_timestam p2); fb_assert(blrOp == blr_current_timestamp || blrOp == blr_current_timestam p2 || blrOp == blr_local_timestamp);
if (blrOp == blr_current_timestamp2) if (blrOp == blr_current_timestamp2 || blrOp == blr_local_timestamp)
{ {
precision = csb->csb_blr_reader.getByte(); precision = csb->csb_blr_reader.getByte();
if (precision > MAX_TIME_PRECISION) if (precision > MAX_TIME_PRECISION)
ERR_post(Arg::Gds(isc_invalid_time_precision) << Arg::Num (MAX_TIME_PRECISION)); ERR_post(Arg::Gds(isc_invalid_time_precision) << Arg::Num (MAX_TIME_PRECISION));
} }
return FB_NEW_POOL(pool) CurrentTimeStampNode(pool, precision); return FB_NEW_POOL(pool) CurrentTimeStampNode(pool, precision);
} }
skipping to change at line 3569 skipping to change at line 3576
{ {
ValueExprNode::internalPrint(printer); ValueExprNode::internalPrint(printer);
NODE_PRINT(printer, precision); NODE_PRINT(printer, precision);
return "CurrentTimeStampNode"; return "CurrentTimeStampNode";
} }
void CurrentTimeStampNode::setParameterName(dsql_par* parameter) 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) 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); dsqlScratch->appendUChar(blr_current_timestamp);
else else
{ {
dsqlScratch->appendUChar(blr_current_timestamp2); dsqlScratch->appendUChar(blr_current_timestamp2);
dsqlScratch->appendUChar(precision); dsqlScratch->appendUChar(precision);
} }
} }
void CurrentTimeStampNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc) void CurrentTimeStampNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
{ {
skipping to change at line 5811 skipping to change at line 5823
// Reference: Bug 10116, 10424 // Reference: Bug 10116, 10424
if (!EVL_field(relation, record, fieldId, &impure->vlu_desc)) if (!EVL_field(relation, record, fieldId, &impure->vlu_desc))
return NULL; return NULL;
// ASF: CORE-1432 - If the record is not on the latest format, upgrade it . // ASF: CORE-1432 - If the record is not on the latest format, upgrade it .
// AP: for fields that are missing in original format use record's one. // AP: for fields that are missing in original format use record's one.
if (format && if (format &&
record->getFormat()->fmt_version != format->fmt_version && record->getFormat()->fmt_version != format->fmt_version &&
fieldId < format->fmt_desc.getCount() && fieldId < format->fmt_desc.getCount() &&
!format->fmt_desc[fieldId].isUnknown() &&
!DSC_EQUIV(&impure->vlu_desc, &format->fmt_desc[fieldId], true)) !DSC_EQUIV(&impure->vlu_desc, &format->fmt_desc[fieldId], true))
{ {
dsc desc = impure->vlu_desc; dsc desc = impure->vlu_desc;
impure->vlu_desc = format->fmt_desc[fieldId]; impure->vlu_desc = format->fmt_desc[fieldId];
if (impure->vlu_desc.isText()) if (impure->vlu_desc.isText())
{ {
// Allocate a string block of sufficient size. // Allocate a string block of sufficient size.
VaryingString* string = impure->vlu_string; VaryingString* string = impure->vlu_string;
skipping to change at line 6718 skipping to change at line 6731
} }
bool LiteralNode::sameAs(const ExprNode* other, bool ignoreStreams) const bool LiteralNode::sameAs(const ExprNode* other, bool ignoreStreams) const
{ {
if (!ExprNode::sameAs(other, ignoreStreams)) if (!ExprNode::sameAs(other, ignoreStreams))
return false; return false;
const LiteralNode* const otherNode = other->as<LiteralNode>(); const LiteralNode* const otherNode = other->as<LiteralNode>();
fb_assert(otherNode); fb_assert(otherNode);
return !MOV_compare(&litDesc, &otherNode->litDesc); try
{
return MOV_compare(&litDesc, &otherNode->litDesc) == 0;
}
catch (const status_exception&)
{
thread_db* tdbb = JRD_get_thread_data();
fb_utils::init_status(tdbb->tdbb_status_vector);
return false;
}
} }
ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb) ValueExprNode* LiteralNode::pass2(thread_db* tdbb, CompilerScratch* csb)
{ {
ValueExprNode::pass2(tdbb, csb); ValueExprNode::pass2(tdbb, csb);
dsc desc; dsc desc;
getDesc(tdbb, csb, &desc); getDesc(tdbb, csb, &desc);
impureOffset = CMP_impure(csb, sizeof(impure_value)); impureOffset = CMP_impure(csb, sizeof(impure_value));
skipping to change at line 7059 skipping to change at line 7081
} }
else if (visitor.context->ctx_scope_level < scope) else if (visitor.context->ctx_scope_level < scope)
doDsqlFieldRemapper(visitor, value); doDsqlFieldRemapper(visitor, value);
return this; return this;
} }
void DerivedFieldNode::setParameterName(dsql_par* parameter) const void DerivedFieldNode::setParameterName(dsql_par* parameter) const
{ {
const dsql_ctx* context = NULL; const dsql_ctx* context = NULL;
const FieldNode* fieldNode; const FieldNode* fieldNode = NULL;
const RecordKeyNode* dbKeyNode; const RecordKeyNode* dbKeyNode = NULL;
if ((fieldNode = value->as<FieldNode>())) const DerivedFieldNode* drvField = value->as<DerivedFieldNode>();
while (drvField)
{
if (fieldNode = drvField->value->as<FieldNode>())
break;
if (dbKeyNode = drvField->value->as<RecordKeyNode>())
break;
drvField = drvField->value->as<DerivedFieldNode>();
};
if (fieldNode || (fieldNode = value->as<FieldNode>()))
{ {
parameter->par_name = fieldNode->dsqlField->fld_name.c_str(); parameter->par_name = fieldNode->dsqlField->fld_name.c_str();
context = fieldNode->dsqlContext; context = fieldNode->dsqlContext;
} }
else if ((dbKeyNode = value->as<RecordKeyNode>())) else if (dbKeyNode || (dbKeyNode = value->as<RecordKeyNode>()))
dbKeyNode->setParameterName(parameter); dbKeyNode->setParameterName(parameter);
parameter->par_alias = name; parameter->par_alias = name;
setParameterInfo(parameter, context); setParameterInfo(parameter, context);
parameter->par_rel_alias = this->context->ctx_alias;
} }
void DerivedFieldNode::genBlr(DsqlCompilerScratch* dsqlScratch) void DerivedFieldNode::genBlr(DsqlCompilerScratch* dsqlScratch)
{ {
// ASF: If we are not referencing a field, we should evaluate the express ion based on // ASF: If we are not referencing a field, we should evaluate the express ion based on
// a set (ORed) of contexts. If any of them are in a valid position the e xpression is // a set (ORed) of contexts. If any of them are in a valid position the e xpression is
// evaluated, otherwise a NULL will be returned. This is fix for CORE-124 6. // evaluated, otherwise a NULL will be returned. This is fix for CORE-124 6.
// Note that the field may be enclosed by an alias. // Note that the field may be enclosed by an alias.
ValueExprNode* val = value; ValueExprNode* val = value;
skipping to change at line 8048 skipping to change at line 8084
break; break;
} }
CharSet* charSet = INTL_charset_lookup(tdbb, DSC_ GET_CHARSET(desc)); CharSet* charSet = INTL_charset_lookup(tdbb, DSC_ GET_CHARSET(desc));
EngineCallbacks::instance->validateData(charSet, len, p); EngineCallbacks::instance->validateData(charSet, len, p);
EngineCallbacks::instance->validateLength(charSet , len, p, maxLen); EngineCallbacks::instance->validateLength(charSet , len, p, maxLen);
} }
else if (desc->isBlob()) else if (desc->isBlob())
{ {
if (desc->getCharSet() != CS_NONE && desc->getCha const bid* const blobId = reinterpret_cast<bid*>(
rSet() != CS_BINARY) desc->dsc_address);
if (!blobId->isEmpty())
{ {
const bid* const blobId = reinterpret_cas if (!request->hasInternalStatement())
t<bid*>(desc->dsc_address); tdbb->getTransaction()->checkBlob
(tdbb, blobId, true);
if (!blobId->isEmpty()) if (desc->getCharSet() != CS_NONE && desc ->getCharSet() != CS_BINARY)
{ {
AutoBlb blob(tdbb, blb::open(tdbb , tdbb->getTransaction(), blobId)); AutoBlb blob(tdbb, blb::open(tdbb , tdbb->getTransaction(), blobId));
blob.getBlb()->BLB_check_well_for med(tdbb, desc); blob.getBlb()->BLB_check_well_for med(tdbb, desc);
} }
} }
} }
} }
if (argInfo) if (argInfo)
{ {
skipping to change at line 11381 skipping to change at line 11420
node->condition = PAR_parse_boolean(tdbb, csb); node->condition = PAR_parse_boolean(tdbb, csb);
node->trueValue = PAR_parse_value(tdbb, csb); node->trueValue = PAR_parse_value(tdbb, csb);
node->falseValue = PAR_parse_value(tdbb, csb); node->falseValue = PAR_parse_value(tdbb, csb);
// Get rid of blr_stmt_expr expressions. // Get rid of blr_stmt_expr expressions.
// Coalesce. // Coalesce.
MissingBoolNode* missing = node->condition->as<MissingBoolNode>(); MissingBoolNode* missing = node->condition->as<MissingBoolNode>();
if (missing) if (missing)
{ {
StmtExprNode* missingCond = missing->arg->as<StmtExprNode>(); StmtExprNode* stmtExpr = missing->arg->as<StmtExprNode>();
if (!missingCond) if (!stmtExpr)
return node; return node;
CompoundStmtNode* stmt = missingCond->stmt->as<CompoundStmtNode>( bool firstAssign = true;
);
DeclareVariableNode* declStmt = NULL;
AssignmentNode* assignStmt; AssignmentNode* assignStmt;
Array<USHORT> nullVariables;
if (stmt) do
{ {
if (stmt->statements.getCount() != 2 || CompoundStmtNode* stmt = stmtExpr->stmt->as<CompoundStmtN
!(declStmt = stmt->statements[0]->as<DeclareVaria ode>();
bleNode>()) || VariableNode* var = NULL;
!(assignStmt = stmt->statements[1]->as<Assignment
Node>())) if (stmt)
{
DeclareVariableNode* declStmt;
if (stmt->statements.getCount() != 2 ||
!(declStmt = stmt->statements[0]->as<Decl
areVariableNode>()) ||
!(assignStmt = stmt->statements[1]->as<As
signmentNode>()) ||
!(var = assignStmt->asgnTo->as<VariableNo
de>()) ||
var->varId != declStmt->varId)
{
return node;
}
}
else if (!(assignStmt = stmtExpr->stmt->as<AssignmentNode
>()) ||
!(var = assignStmt->asgnTo->as<VariableNode>()))
{ {
return node; return node;
} }
}
else if (!(assignStmt = missingCond->stmt->as<AssignmentNode>()))
return node;
VariableNode* var = node->falseValue->as<VariableNode>(); nullVariables.add(var->varId);
VariableNode* var2 = assignStmt->asgnTo->as<VariableNode>();
if (!var || !var2 || var->varId != var2->varId || (declStmt && de if (firstAssign)
clStmt->varId != var->varId)) {
return node; firstAssign = false;
VariableNode* var2 = node->falseValue->as<Variabl
eNode>();
if (!var2 || var->varId != var2->varId)
return node;
}
stmtExpr = assignStmt->asgnFrom->as<StmtExprNode>();
} while (stmtExpr);
CoalesceNode* coalesceNode = FB_NEW_POOL(pool) CoalesceNode(pool) ; CoalesceNode* coalesceNode = FB_NEW_POOL(pool) CoalesceNode(pool) ;
coalesceNode->args = FB_NEW_POOL(pool) ValueListNode(pool, 2); coalesceNode->args = FB_NEW_POOL(pool) ValueListNode(pool, 2);
coalesceNode->args->items[0] = assignStmt->asgnFrom; coalesceNode->args->items[0] = assignStmt->asgnFrom;
coalesceNode->args->items[1] = node->trueValue; coalesceNode->args->items[1] = node->trueValue;
// Variables known to be NULL may be removed from the coalesce. T
his is not only an optimization!
// If not removed, error will happen as they correspondents decla
re nodes were removed.
if (CoalesceNode* subCoalesceNode = node->trueValue->as<CoalesceN
ode>())
{
NestValueArray& childItems = subCoalesceNode->args->items
;
for (int i = childItems.getCount() - 1; i >= 0; --i)
{
if (VariableNode* childVar = childItems[i]->as<Va
riableNode>())
{
if (nullVariables.exist(childVar->varId))
childItems.remove(i);
}
}
}
return coalesceNode; return coalesceNode;
} }
// Decode. // Decode.
ComparativeBoolNode* cmp = node->condition->as<ComparativeBoolNode>(); ComparativeBoolNode* cmp = node->condition->as<ComparativeBoolNode>();
if (cmp && cmp->blrOp == blr_eql) if (cmp && cmp->blrOp == blr_eql)
{ {
StmtExprNode* cmpCond = cmp->arg1->as<StmtExprNode>(); StmtExprNode* cmpCond = cmp->arg1->as<StmtExprNode>();
if (!cmpCond) if (!cmpCond)
return node; return node;
 End of changes. 29 change blocks. 
38 lines changed or deleted 121 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)