mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 09:20:39 +01:00
Fix nodDesc of NullNode being changed after its initial construction.
This commit is contained in:
parent
6ca9b607ba
commit
a329a92786
@ -394,7 +394,7 @@ string ValueExprNode::internalPrint(NodePrinter& printer) const
|
||||
ExprNode::internalPrint(printer);
|
||||
|
||||
NODE_PRINT(printer, nodScale);
|
||||
NODE_PRINT(printer, nodDesc);
|
||||
NODE_PRINT(printer, getDsqlDesc());
|
||||
|
||||
return "ValueExprNode";
|
||||
}
|
||||
@ -3390,9 +3390,9 @@ ValueExprNode* CastNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
node->setParameterType(dsqlScratch, NULL, false);
|
||||
|
||||
DsqlDescMaker::fromField(&node->castDesc, node->dsqlField);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &node->source->nodDesc, node->source);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, node->source);
|
||||
|
||||
node->castDesc.dsc_flags = node->source->nodDesc.dsc_flags & DSC_nullable;
|
||||
node->castDesc.dsc_flags = node->source->getDsqlDesc().dsc_flags & DSC_nullable;
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -3628,7 +3628,7 @@ ValueExprNode* CoalesceNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
CoalesceNode* node = FB_NEW_POOL(dsqlScratch->getPool()) CoalesceNode(
|
||||
dsqlScratch->getPool(), doDsqlPass(dsqlScratch, args));
|
||||
|
||||
node->make(dsqlScratch, &node->nodDesc); // Set descriptor for output node.
|
||||
node->makeDsqlDesc(dsqlScratch); // Set descriptor for output node.
|
||||
|
||||
for (auto& item : node->args->items)
|
||||
PASS1_set_parameter_type(dsqlScratch, item, node, false);
|
||||
@ -3753,12 +3753,12 @@ ValueExprNode* CollateNode::pass1Collate(DsqlCompilerScratch* dsqlScratch, Value
|
||||
dsql_fld* field = FB_NEW_POOL(pool) dsql_fld(pool);
|
||||
CastNode* castNode = FB_NEW_POOL(pool) CastNode(pool, input, field);
|
||||
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &input->nodDesc, input);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, input);
|
||||
|
||||
if (input->nodDesc.dsc_dtype <= dtype_any_text ||
|
||||
(input->nodDesc.dsc_dtype == dtype_blob && input->nodDesc.dsc_sub_type == isc_blob_text))
|
||||
if (input->getDsqlDesc().dsc_dtype <= dtype_any_text ||
|
||||
(input->getDsqlDesc().dsc_dtype == dtype_blob && input->getDsqlDesc().dsc_sub_type == isc_blob_text))
|
||||
{
|
||||
assignFieldDtypeFromDsc(field, &input->nodDesc);
|
||||
assignFieldDtypeFromDsc(field, &input->getDsqlDesc());
|
||||
field->charLength = 0;
|
||||
}
|
||||
else
|
||||
@ -4605,10 +4605,10 @@ ValueExprNode* DecodeNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
doDsqlPass(dsqlScratch, test), doDsqlPass(dsqlScratch, conditions), doDsqlPass(dsqlScratch, values));
|
||||
node->label = label;
|
||||
|
||||
node->make(dsqlScratch, &node->nodDesc); // Set descriptor for output node.
|
||||
node->makeDsqlDesc(dsqlScratch); // Set descriptor for output node.
|
||||
|
||||
node->setParameterType(dsqlScratch,
|
||||
[&] (dsc* desc) { *desc = node->nodDesc; },
|
||||
[&] (dsc* desc) { *desc = node->getDsqlDesc(); },
|
||||
false);
|
||||
|
||||
// Workaround for DECODE/CASE supporting only 255 items - see CORE-5366.
|
||||
@ -5270,7 +5270,7 @@ ValueExprNode* ExtractNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
// sure the requested type of information can be extracted.
|
||||
|
||||
ValueExprNode* sub1 = doDsqlPass(dsqlScratch, arg);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &sub1->nodDesc, sub1);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, sub1);
|
||||
|
||||
switch (blrSubOp)
|
||||
{
|
||||
@ -5281,8 +5281,8 @@ ValueExprNode* ExtractNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
case blr_extract_yearday:
|
||||
case blr_extract_week:
|
||||
if (!nodeIs<NullNode>(sub1) &&
|
||||
sub1->nodDesc.dsc_dtype != dtype_sql_date &&
|
||||
!sub1->nodDesc.isTimeStamp())
|
||||
sub1->getDsqlDesc().dsc_dtype != dtype_sql_date &&
|
||||
!sub1->getDsqlDesc().isTimeStamp())
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-105) <<
|
||||
Arg::Gds(isc_extract_input_mismatch));
|
||||
@ -5294,8 +5294,8 @@ ValueExprNode* ExtractNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
case blr_extract_second:
|
||||
case blr_extract_millisecond:
|
||||
if (!nodeIs<NullNode>(sub1) &&
|
||||
!sub1->nodDesc.isTime() &&
|
||||
!sub1->nodDesc.isTimeStamp())
|
||||
!sub1->getDsqlDesc().isTime() &&
|
||||
!sub1->getDsqlDesc().isTimeStamp())
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-105) <<
|
||||
Arg::Gds(isc_extract_input_mismatch));
|
||||
@ -5305,8 +5305,8 @@ ValueExprNode* ExtractNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
case blr_extract_timezone_hour:
|
||||
case blr_extract_timezone_minute:
|
||||
if (!nodeIs<NullNode>(sub1) &&
|
||||
!sub1->nodDesc.isTime() &&
|
||||
!sub1->nodDesc.isTimeStamp())
|
||||
!sub1->getDsqlDesc().isTime() &&
|
||||
!sub1->getDsqlDesc().isTimeStamp())
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-105) <<
|
||||
Arg::Gds(isc_extract_input_mismatch));
|
||||
@ -6408,8 +6408,8 @@ void FieldNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
void FieldNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc)
|
||||
{
|
||||
if (nodDesc.dsc_dtype)
|
||||
*desc = nodDesc;
|
||||
if (getDsqlDesc().dsc_dtype)
|
||||
*desc = getDsqlDesc();
|
||||
else
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-203) <<
|
||||
@ -8216,7 +8216,7 @@ ValueExprNode* DsqlAliasNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
DsqlAliasNode* node = FB_NEW_POOL(dsqlScratch->getPool()) DsqlAliasNode(dsqlScratch->getPool(), name,
|
||||
doDsqlPass(dsqlScratch, value));
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &node->value->nodDesc, node->value);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, node->value);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -8243,7 +8243,9 @@ void DsqlAliasNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
DsqlMapNode::DsqlMapNode(MemoryPool& pool, dsql_ctx* aContext, dsql_map* aMap)
|
||||
: TypedNode<ValueExprNode, ExprNode::TYPE_MAP>(pool),
|
||||
context(aContext),
|
||||
map(aMap)
|
||||
map(aMap),
|
||||
setNullable(false),
|
||||
clearNull(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -8253,6 +8255,8 @@ string DsqlMapNode::internalPrint(NodePrinter& printer) const
|
||||
|
||||
NODE_PRINT(printer, context);
|
||||
NODE_PRINT(printer, map);
|
||||
NODE_PRINT(printer, setNullable);
|
||||
NODE_PRINT(printer, clearNull);
|
||||
|
||||
return "DsqlMapNode";
|
||||
}
|
||||
@ -8397,8 +8401,11 @@ void DsqlMapNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
DsqlDescMaker::fromNode(dsqlScratch, desc, map->map_node);
|
||||
|
||||
// ASF: We should mark nod_agg_count as nullable when it's in an outer join - CORE-2660.
|
||||
if (context->ctx_flags & CTX_outer_join)
|
||||
if (setNullable || (context->ctx_flags & CTX_outer_join))
|
||||
desc->setNullable(true);
|
||||
|
||||
if (clearNull)
|
||||
desc->clearNull();
|
||||
}
|
||||
|
||||
bool DsqlMapNode::dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const
|
||||
@ -12079,8 +12086,8 @@ void SysFuncCallNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
|
||||
for (auto& arg : args->items)
|
||||
{
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &arg->nodDesc, arg);
|
||||
argsArray.add(&arg->nodDesc);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, arg);
|
||||
argsArray.add(&arg->getDsqlDesc());
|
||||
}
|
||||
|
||||
DSqlDataTypeUtil dataTypeUtil(dsqlScratch);
|
||||
@ -12207,12 +12214,24 @@ ValueExprNode* SysFuncCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
|
||||
if (node->function->setParamsFunc)
|
||||
{
|
||||
Array<dsc*> argsArray;
|
||||
Array<dsc> tempDescs(node->args->items.getCount());
|
||||
tempDescs.resize(node->args->items.getCount());
|
||||
|
||||
Array<dsc*> argsArray(node->args->items.getCount());
|
||||
|
||||
for (auto& item : node->args->items)
|
||||
{
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &item->nodDesc, item);
|
||||
argsArray.add(&item->nodDesc);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, item);
|
||||
|
||||
auto itemDesc = item->dsqlSetableDesc();
|
||||
|
||||
if (!itemDesc)
|
||||
{
|
||||
tempDescs.push(item->getDsqlDesc());
|
||||
itemDesc = &tempDescs.back();
|
||||
}
|
||||
|
||||
argsArray.add(itemDesc);
|
||||
}
|
||||
|
||||
DSqlDataTypeUtil dataTypeUtil(dsqlScratch);
|
||||
@ -12222,7 +12241,7 @@ ValueExprNode* SysFuncCallNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
for (auto& item : node->args->items)
|
||||
{
|
||||
PASS1_set_parameter_type(dsqlScratch, item,
|
||||
[&] (dsc* desc) { *desc = item->nodDesc; },
|
||||
[&] (dsc* desc) { *desc = item->getDsqlDesc(); },
|
||||
false);
|
||||
}
|
||||
}
|
||||
@ -13310,11 +13329,11 @@ void ValueIfNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc)
|
||||
{
|
||||
Array<const dsc*> args;
|
||||
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &trueValue->nodDesc, trueValue);
|
||||
args.add(&trueValue->nodDesc);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, trueValue);
|
||||
args.add(&trueValue->getDsqlDesc());
|
||||
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &falseValue->nodDesc, falseValue);
|
||||
args.add(&falseValue->nodDesc);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, falseValue);
|
||||
args.add(&falseValue->getDsqlDesc());
|
||||
|
||||
DSqlDataTypeUtil(dsqlScratch).makeFromList(desc, "CASE", args.getCount(), args.begin());
|
||||
}
|
||||
|
@ -258,6 +258,11 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
|
||||
void setDsqlDesc(const dsc& desc)
|
||||
{
|
||||
dsqlDesc = desc;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
|
||||
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
|
||||
@ -765,6 +770,11 @@ public:
|
||||
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
|
||||
virtual bool sameAs(CompilerScratch* csb, const ExprNode* other, bool ignoreStreams) const;
|
||||
|
||||
void setDsqlDesc(const dsc& desc)
|
||||
{
|
||||
dsqlDesc = desc;
|
||||
}
|
||||
|
||||
virtual bool possiblyUnknown(OptimizerBlk* /*opt*/)
|
||||
{
|
||||
return false;
|
||||
@ -964,6 +974,11 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
|
||||
void setDsqlDesc(const dsc& desc)
|
||||
{
|
||||
dsqlDesc = desc;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* /*desc*/)
|
||||
{
|
||||
fb_assert(false);
|
||||
@ -1008,6 +1023,11 @@ public:
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
|
||||
|
||||
void setDsqlDesc(const dsc& desc)
|
||||
{
|
||||
dsqlDesc = desc;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* /*desc*/)
|
||||
{
|
||||
fb_assert(false);
|
||||
@ -1028,6 +1048,8 @@ public:
|
||||
public:
|
||||
dsql_ctx* context;
|
||||
dsql_map* map;
|
||||
bool setNullable;
|
||||
bool clearNull;
|
||||
};
|
||||
|
||||
|
||||
@ -1059,6 +1081,11 @@ public:
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
|
||||
void setDsqlDesc(const dsc& desc)
|
||||
{
|
||||
dsqlDesc = desc;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* /*tdbb*/, CompilerScratch* /*csb*/, dsc* /*desc*/)
|
||||
{
|
||||
fb_assert(false);
|
||||
@ -1177,6 +1204,7 @@ private:
|
||||
explicit NullNode(MemoryPool& pool)
|
||||
: TypedNode<ValueExprNode, ExprNode::TYPE_NULL>(pool)
|
||||
{
|
||||
dsqlDesc.makeNullString();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1187,6 +1215,11 @@ public:
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, const UCHAR blrOp);
|
||||
|
||||
virtual bool isSharedNode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual Firebird::string internalPrint(NodePrinter& printer) const;
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
@ -2141,6 +2174,11 @@ public:
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc);
|
||||
virtual bool dsqlMatch(DsqlCompilerScratch* dsqlScratch, const ExprNode* other, bool ignoreMapCast) const;
|
||||
|
||||
void setDsqlDesc(const dsc& desc)
|
||||
{
|
||||
dsqlDesc = desc;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) const;
|
||||
virtual ValueExprNode* pass1(thread_db* tdbb, CompilerScratch* csb);
|
||||
|
@ -747,7 +747,7 @@ public:
|
||||
: ExprNode(aType, pool),
|
||||
nodScale(0)
|
||||
{
|
||||
nodDesc.clear();
|
||||
dsqlDesc.clear();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -758,6 +758,30 @@ public:
|
||||
return KIND_VALUE;
|
||||
}
|
||||
|
||||
const dsc& getDsqlDesc() const
|
||||
{
|
||||
return dsqlDesc;
|
||||
}
|
||||
|
||||
void makeDsqlDesc(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
auto settableDesc = dsqlSetableDesc();
|
||||
|
||||
if (settableDesc)
|
||||
make(dsqlScratch, settableDesc);
|
||||
}
|
||||
|
||||
dsc* dsqlSetableDesc()
|
||||
{
|
||||
return isSharedNode() ? nullptr : &dsqlDesc;
|
||||
}
|
||||
|
||||
// Must be overriden returning true in shared nodes.
|
||||
virtual bool isSharedNode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
ExprNode::dsqlPass(dsqlScratch);
|
||||
@ -799,7 +823,9 @@ public:
|
||||
|
||||
public:
|
||||
SCHAR nodScale;
|
||||
dsc nodDesc;
|
||||
|
||||
protected:
|
||||
dsc dsqlDesc;
|
||||
};
|
||||
|
||||
template <typename T, typename ValueExprNode::Type typeConst>
|
||||
|
@ -9388,7 +9388,7 @@ static VariableNode* dsqlPassHiddenVariable(DsqlCompilerScratch* dsqlScratch, Va
|
||||
0, 0, dsqlScratch->hiddenVarsNumber++);
|
||||
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &varNode->dsqlVar->desc, expr);
|
||||
varNode->nodDesc = varNode->dsqlVar->desc;
|
||||
varNode->setDsqlDesc(varNode->dsqlVar->desc);
|
||||
|
||||
return varNode;
|
||||
}
|
||||
@ -9592,7 +9592,7 @@ static void dsqlSetParameterName(DsqlCompilerScratch* dsqlScratch, ExprNode* exp
|
||||
const FieldNode* fieldNode = nodeAs<FieldNode>(fld_node);
|
||||
fb_assert(fieldNode); // Could it be something else ???
|
||||
|
||||
if (fieldNode->nodDesc.dsc_dtype != dtype_array)
|
||||
if (fieldNode->getDsqlDesc().dsc_dtype != dtype_array)
|
||||
return;
|
||||
|
||||
switch (exprNode->getType())
|
||||
|
@ -90,8 +90,8 @@ void DsqlDescMaker::fromList(DsqlCompilerScratch* scratch, dsc* desc,
|
||||
|
||||
while (p != end)
|
||||
{
|
||||
DsqlDescMaker::fromNode(scratch, &(*p)->nodDesc, *p);
|
||||
args.add(&(*p)->nodDesc);
|
||||
DsqlDescMaker::fromNode(scratch, *p);
|
||||
args.add(&(*p)->getDsqlDesc());
|
||||
++p;
|
||||
}
|
||||
|
||||
@ -106,14 +106,23 @@ void DsqlDescMaker::fromNode(DsqlCompilerScratch* scratch, dsc* desc,
|
||||
DEV_BLKCHK(node, dsql_type_nod);
|
||||
|
||||
// If we already know the datatype, don't worry about anything.
|
||||
if (node->nodDesc.dsc_dtype)
|
||||
*desc = node->nodDesc;
|
||||
if (node->getDsqlDesc().dsc_dtype)
|
||||
*desc = node->getDsqlDesc();
|
||||
else
|
||||
node->make(scratch, desc);
|
||||
|
||||
desc->dsc_flags |= nullable ? DSC_nullable : 0;
|
||||
}
|
||||
|
||||
void DsqlDescMaker::fromNode(DsqlCompilerScratch* scratch, ValueExprNode* node)
|
||||
{
|
||||
DEV_BLKCHK(node, dsql_type_nod);
|
||||
|
||||
// If we already know the datatype, don't worry about anything.
|
||||
if (!node->getDsqlDesc().dsc_dtype)
|
||||
node->makeDsqlDesc(scratch);
|
||||
}
|
||||
|
||||
void DsqlDescMaker::composeDesc(dsc* desc,
|
||||
USHORT dtype,
|
||||
SSHORT scale,
|
||||
@ -374,19 +383,22 @@ FieldNode* MAKE_field(dsql_ctx* context, dsql_fld* field, ValueListNode* indices
|
||||
FieldNode* const node = FB_NEW_POOL(*tdbb->getDefaultPool()) FieldNode(
|
||||
*tdbb->getDefaultPool(), context, field, indices);
|
||||
|
||||
dsc desc;
|
||||
|
||||
if (field->dimensions)
|
||||
{
|
||||
if (indices)
|
||||
{
|
||||
DsqlDescMaker::fromElement(&node->nodDesc, field);
|
||||
}
|
||||
DsqlDescMaker::fromElement(&desc, field);
|
||||
else
|
||||
{
|
||||
node->nodDesc.dsc_dtype = dtype_array;
|
||||
node->nodDesc.dsc_length = sizeof(ISC_QUAD);
|
||||
node->nodDesc.dsc_scale = static_cast<SCHAR>(field->scale);
|
||||
node->nodDesc.dsc_sub_type = field->subType;
|
||||
desc = node->getDsqlDesc();
|
||||
desc.dsc_dtype = dtype_array;
|
||||
desc.dsc_length = sizeof(ISC_QUAD);
|
||||
desc.dsc_scale = static_cast<SCHAR>(field->scale);
|
||||
desc.dsc_sub_type = field->subType;
|
||||
}
|
||||
|
||||
node->setDsqlDesc(desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -396,11 +408,16 @@ FieldNode* MAKE_field(dsql_ctx* context, dsql_fld* field, ValueListNode* indices
|
||||
Arg::Gds(isc_dsql_only_can_subscript_array) << Arg::Str(field->fld_name));
|
||||
}
|
||||
|
||||
DsqlDescMaker::fromField(&node->nodDesc, field);
|
||||
DsqlDescMaker::fromField(&desc, field);
|
||||
node->setDsqlDesc(desc);
|
||||
}
|
||||
|
||||
if ((field->flags & FLD_nullable) || (context->ctx_flags & CTX_outer_join))
|
||||
node->nodDesc.dsc_flags |= DSC_nullable;
|
||||
{
|
||||
desc = node->getDsqlDesc();
|
||||
desc.dsc_flags |= DSC_nullable;
|
||||
node->setDsqlDesc(desc);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -64,6 +64,7 @@ namespace Jrd {
|
||||
ValueListNode*, const char*, bool = false);
|
||||
static void fromNode(DsqlCompilerScratch*, dsc*,
|
||||
ValueExprNode*, bool = false);
|
||||
static void fromNode(DsqlCompilerScratch*, ValueExprNode*);
|
||||
|
||||
private:
|
||||
static void composeDesc(dsc* desc,
|
||||
|
@ -1066,8 +1066,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
|
||||
// the worse thing is that a UNION currently can't be used in
|
||||
// deciding the JOIN order.
|
||||
bool foundSubSelect = false;
|
||||
RseNode* queryNode = nodeAs<RseNode>(query);
|
||||
if (queryNode)
|
||||
if (auto queryNode = nodeAs<RseNode>(query))
|
||||
foundSubSelect = SubSelectFinder::find(dsqlScratch->getPool(), queryNode->dsqlSelectList);
|
||||
|
||||
if (foundSubSelect)
|
||||
@ -1146,13 +1145,13 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
|
||||
for (FB_SIZE_T count = 0; count < input->columns->getCount(); ++count)
|
||||
{
|
||||
ValueExprNode* select_item = rse->dsqlSelectList->items[count];
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &select_item->nodDesc, select_item);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, select_item);
|
||||
|
||||
// Make new derived field node.
|
||||
|
||||
DerivedFieldNode* derivedField = FB_NEW_POOL(pool) DerivedFieldNode(pool,
|
||||
(*input->columns)[count], dsqlScratch->scopeLevel, select_item);
|
||||
derivedField->nodDesc = select_item->nodDesc;
|
||||
derivedField->setDsqlDesc(select_item->getDsqlDesc());
|
||||
rse->dsqlSelectList->items[count] = derivedField;
|
||||
}
|
||||
}
|
||||
@ -1168,7 +1167,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
|
||||
// Auto-create dummy column name for pass1_any()
|
||||
if (ignoreColumnChecks && !nodeIs<DerivedFieldNode>(select_item))
|
||||
{
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &select_item->nodDesc, select_item);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, select_item);
|
||||
|
||||
// Construct dummy fieldname
|
||||
char fieldname[25];
|
||||
@ -1178,7 +1177,7 @@ RseNode* PASS1_derived_table(DsqlCompilerScratch* dsqlScratch, SelectExprNode* i
|
||||
|
||||
DerivedFieldNode* derivedField = FB_NEW_POOL(pool) DerivedFieldNode(pool,
|
||||
fieldname, dsqlScratch->scopeLevel, select_item);
|
||||
derivedField->nodDesc = select_item->nodDesc;
|
||||
derivedField->setDsqlDesc(select_item->getDsqlDesc());
|
||||
select_item = derivedField;
|
||||
}
|
||||
|
||||
@ -1655,7 +1654,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
|
||||
// Create a derived field and ignore alias node.
|
||||
DerivedFieldNode* newField = FB_NEW_POOL(pool) DerivedFieldNode(pool,
|
||||
aliasNode->name, dsqlScratch->scopeLevel, aliasNode->value);
|
||||
newField->nodDesc = aliasNode->value->nodDesc;
|
||||
newField->setDsqlDesc(aliasNode->value->getDsqlDesc());
|
||||
return newField;
|
||||
}
|
||||
else if ((subQueryNode = nodeAs<SubQueryNode>(select_item)))
|
||||
@ -1680,7 +1679,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
|
||||
{
|
||||
derivedField->value = select_item;
|
||||
derivedField->scope = dsqlScratch->scopeLevel;
|
||||
derived_field->nodDesc = select_item->nodDesc;
|
||||
derivedField->setDsqlDesc(select_item->getDsqlDesc());
|
||||
return derived_field;
|
||||
}
|
||||
}
|
||||
@ -1690,7 +1689,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
|
||||
|
||||
DerivedFieldNode* newField = FB_NEW_POOL(pool) DerivedFieldNode(pool,
|
||||
fieldNode->dsqlField->fld_name, dsqlScratch->scopeLevel, select_item);
|
||||
newField->nodDesc = fieldNode->nodDesc;
|
||||
newField->setDsqlDesc(fieldNode->getDsqlDesc());
|
||||
return newField;
|
||||
}
|
||||
else if ((derivedField = nodeAs<DerivedFieldNode>(select_item)))
|
||||
@ -1699,7 +1698,7 @@ static ValueExprNode* pass1_make_derived_field(thread_db* tdbb, DsqlCompilerScra
|
||||
|
||||
DerivedFieldNode* newField = FB_NEW_POOL(pool) DerivedFieldNode(pool,
|
||||
derivedField->name, dsqlScratch->scopeLevel, select_item);
|
||||
newField->nodDesc = select_item->nodDesc;
|
||||
newField->setDsqlDesc(select_item->getDsqlDesc());
|
||||
return newField;
|
||||
}
|
||||
|
||||
@ -1797,10 +1796,7 @@ static RseNode* pass1_rse_impl(DsqlCompilerScratch* dsqlScratch, RecordSourceNod
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
MemoryPool& pool = *tdbb->getDefaultPool();
|
||||
|
||||
SelectExprNode* selNode = nodeAs<SelectExprNode>(input);
|
||||
UnionSourceNode* unionNode = nodeAs<UnionSourceNode>(input);
|
||||
|
||||
if (selNode)
|
||||
if (auto selNode = nodeAs<SelectExprNode>(input))
|
||||
{
|
||||
WithClause* withClause = selNode->withClause;
|
||||
try
|
||||
@ -1826,7 +1822,7 @@ static RseNode* pass1_rse_impl(DsqlCompilerScratch* dsqlScratch, RecordSourceNod
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else if (unionNode)
|
||||
else if (auto unionNode = nodeAs<UnionSourceNode>(input))
|
||||
{
|
||||
fb_assert(unionNode->dsqlClauses->items.hasData());
|
||||
return pass1_union(dsqlScratch, unionNode, order, rows, updateLock, flags);
|
||||
@ -2532,31 +2528,21 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
|
||||
ValueListNode* tmp_list = FB_NEW_POOL(pool) ValueListNode(
|
||||
pool, unionSource->dsqlClauses->items.getCount());
|
||||
|
||||
Array<dsc> descs(unionSource->dsqlClauses->items.getCount());
|
||||
|
||||
for (FB_SIZE_T j = 0; j < items->items.getCount(); ++j)
|
||||
{
|
||||
for (FB_SIZE_T i = 0; i < unionSource->dsqlClauses->items.getCount(); ++i)
|
||||
{
|
||||
ValueListNode* nod1 = nodeAs<RseNode>(unionSource->dsqlClauses->items[i])->dsqlSelectList;
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &nod1->items[j]->nodDesc, nod1->items[j]);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, nod1->items[j]);
|
||||
tmp_list->items[i] = nod1->items[j];
|
||||
|
||||
// We look only at the items->nod_arg[] when creating the
|
||||
// output descriptors. Make sure that the sub-rses
|
||||
// descriptor flags are copied onto items->nod_arg[]->nodDesc.
|
||||
// Bug 65584.
|
||||
// -Sudesh 07/28/1999.
|
||||
if (i > 0)
|
||||
{
|
||||
if (nod1->items[j]->nodDesc.dsc_flags & DSC_nullable)
|
||||
items->items[j]->nodDesc.dsc_flags |= DSC_nullable;
|
||||
}
|
||||
}
|
||||
|
||||
dsc desc;
|
||||
DsqlDescMaker::fromList(dsqlScratch, &desc, tmp_list, "UNION");
|
||||
// Only mark upper node as a NULL node when all sub-nodes are NULL
|
||||
items->items[j]->nodDesc.dsc_flags &= ~DSC_null;
|
||||
items->items[j]->nodDesc.dsc_flags |= (desc.dsc_flags & DSC_null);
|
||||
|
||||
descs.push(desc);
|
||||
|
||||
pass1_union_auto_cast(dsqlScratch, unionSource->dsqlClauses, desc, j);
|
||||
}
|
||||
@ -2583,7 +2569,18 @@ static RseNode* pass1_union(DsqlCompilerScratch* dsqlScratch, UnionSourceNode* i
|
||||
map->map_window = NULL;
|
||||
union_context->ctx_map = map;
|
||||
|
||||
*ptr = FB_NEW_POOL(pool) DsqlMapNode(pool, union_context, map);
|
||||
auto mapNode = FB_NEW_POOL(pool) DsqlMapNode(pool, union_context, map);
|
||||
|
||||
if (descs[map->map_position].dsc_flags & DSC_nullable)
|
||||
mapNode->setNullable = true;
|
||||
|
||||
if ((items->items[map->map_position]->getDsqlDesc().dsc_flags & DSC_null) &&
|
||||
!(descs[map->map_position].dsc_flags & DSC_null))
|
||||
{
|
||||
mapNode->clearNull = true;
|
||||
}
|
||||
|
||||
*ptr = mapNode;
|
||||
}
|
||||
|
||||
unionRse->dsqlSelectList = union_items;
|
||||
@ -2701,13 +2698,15 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
|
||||
(unionNode = nodeAs<UnionSourceNode>(rseNode->dsqlStreams->items[0])) &&
|
||||
unionNode->dsqlParentRse == rseNode)
|
||||
{
|
||||
// We're now in a UNION under a UNION so don't change the existing mappings.
|
||||
// We're now in a UNION under a UNION (for example A UNION ALL B UNION C) so don't
|
||||
// change the existing mappings.
|
||||
// Only replace the node where the map points to, because they could be changed.
|
||||
ValueListNode* sub_rse_items =
|
||||
nodeAs<RseNode>(unionNode->dsqlClauses->items[0])->dsqlSelectList;
|
||||
dsql_map* map = nodeAs<DsqlMapNode>(rseNode->dsqlSelectList->items[position])->map;
|
||||
auto mapNode = nodeAs<DsqlMapNode>(rseNode->dsqlSelectList->items[position]);
|
||||
dsql_map* map = mapNode->map;
|
||||
map->map_node = sub_rse_items->items[position];
|
||||
rseNode->dsqlSelectList->items[position]->nodDesc = desc;
|
||||
mapNode->setDsqlDesc(desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2723,12 +2722,12 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
|
||||
else
|
||||
{
|
||||
ValueExprNode* select_item = list->items[position];
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &select_item->nodDesc, select_item);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, select_item);
|
||||
|
||||
if (select_item->nodDesc.dsc_dtype != desc.dsc_dtype ||
|
||||
select_item->nodDesc.dsc_length != desc.dsc_length ||
|
||||
select_item->nodDesc.dsc_scale != desc.dsc_scale ||
|
||||
select_item->nodDesc.dsc_sub_type != desc.dsc_sub_type)
|
||||
if (select_item->getDsqlDesc().dsc_dtype != desc.dsc_dtype ||
|
||||
select_item->getDsqlDesc().dsc_length != desc.dsc_length ||
|
||||
select_item->getDsqlDesc().dsc_scale != desc.dsc_scale ||
|
||||
select_item->getDsqlDesc().dsc_sub_type != desc.dsc_sub_type)
|
||||
{
|
||||
// Because this select item has a different descriptor then
|
||||
// our finally descriptor CAST it.
|
||||
@ -2750,7 +2749,7 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
|
||||
else
|
||||
castNode = nodeAs<CastNode>(select_item);
|
||||
|
||||
if (castNode && !DSC_EQUIV(&castNode->nodDesc, &desc, false))
|
||||
if (castNode && !DSC_EQUIV(&castNode->getDsqlDesc(), &desc, false))
|
||||
castNode = NULL;
|
||||
|
||||
if (!castNode)
|
||||
@ -2782,9 +2781,7 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
|
||||
name_node = mapNode->map->map_node;
|
||||
}
|
||||
|
||||
const FieldNode* fieldNode;
|
||||
|
||||
if ((fieldNode = nodeAs<FieldNode>(name_node)))
|
||||
if (auto fieldNode = nodeAs<FieldNode>(name_node))
|
||||
{
|
||||
// Create new node for alias and copy fieldname.
|
||||
newAliasNode = FB_NEW_POOL(*tdbb->getDefaultPool()) DsqlAliasNode(
|
||||
@ -2823,31 +2820,32 @@ static void pass1_union_auto_cast(DsqlCompilerScratch* dsqlScratch, ExprNode* in
|
||||
|
||||
// Finally copy the descriptors to the root nodes and swap
|
||||
// the necessary nodes.
|
||||
castNode->nodDesc = desc;
|
||||
|
||||
if (select_item->nodDesc.dsc_flags & DSC_nullable)
|
||||
castNode->nodDesc.dsc_flags |= DSC_nullable;
|
||||
castNode->setDsqlDesc(desc);
|
||||
|
||||
if ((aliasNode = nodeAs<DsqlAliasNode>(select_item)))
|
||||
{
|
||||
aliasNode->value = castNode;
|
||||
aliasNode->value->nodDesc = desc;
|
||||
select_item->nodDesc = desc;
|
||||
aliasNode->setDsqlDesc(desc);
|
||||
}
|
||||
else if ((derivedField = nodeAs<DerivedFieldNode>(select_item)))
|
||||
{
|
||||
derivedField->value = castNode;
|
||||
derivedField->value->nodDesc = desc;
|
||||
select_item->nodDesc = desc;
|
||||
derivedField->setDsqlDesc(desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (select_item->getDsqlDesc().dsc_flags & DSC_nullable)
|
||||
{
|
||||
dsc castDesc = castNode->getDsqlDesc();
|
||||
castDesc.dsc_flags |= DSC_nullable;
|
||||
castNode->setDsqlDesc(castDesc);
|
||||
}
|
||||
|
||||
// If a new alias was created for keeping original field-name
|
||||
// make the alias the "top" node.
|
||||
if (newAliasNode)
|
||||
{
|
||||
newAliasNode->value = castNode;
|
||||
newAliasNode->value->nodDesc = castNode->nodDesc;
|
||||
list->items[position] = newAliasNode;
|
||||
}
|
||||
else
|
||||
@ -2918,7 +2916,7 @@ DsqlMapNode* PASS1_post_map(DsqlCompilerScratch* dsqlScratch, ValueExprNode* nod
|
||||
map->map_window = windowMap;
|
||||
}
|
||||
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &node->nodDesc, node);
|
||||
DsqlDescMaker::fromNode(dsqlScratch, node);
|
||||
|
||||
return FB_NEW_POOL(*tdbb->getDefaultPool()) DsqlMapNode(*tdbb->getDefaultPool(), context, map);
|
||||
}
|
||||
@ -2977,8 +2975,8 @@ bool PASS1_set_parameter_type(DsqlCompilerScratch* dsqlScratch, ValueExprNode* i
|
||||
|
||||
auto makeDesc = [&] (dsc* desc)
|
||||
{
|
||||
DsqlDescMaker::fromNode(dsqlScratch, &node->nodDesc, node);
|
||||
*desc = node->nodDesc;
|
||||
DsqlDescMaker::fromNode(dsqlScratch, node);
|
||||
*desc = node->getDsqlDesc();
|
||||
};
|
||||
|
||||
return inNode->setParameterType(dsqlScratch, makeDesc, forceVarchar);
|
||||
|
Loading…
Reference in New Issue
Block a user