mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 19:23:02 +01:00
Refactor parameters and GEN_ID.
This commit is contained in:
parent
9bf9ca4ef7
commit
4d00fec2d6
@ -452,7 +452,8 @@ DmlNode* AvgAggNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* c
|
||||
return node;
|
||||
}
|
||||
|
||||
void AvgAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void AvgAggNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlArg, nullReplacement);
|
||||
desc->setNullable(true);
|
||||
@ -657,15 +658,16 @@ DmlNode* ListAggNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
return node;
|
||||
}
|
||||
|
||||
void ListAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void ListAggNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlArg, nullReplacement);
|
||||
desc->makeBlob(desc->getBlobSubType(), desc->getTextType());
|
||||
desc->setNullable(true);
|
||||
}
|
||||
|
||||
bool ListAggNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
bool ListAggNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlArg, node, forceVarChar) |
|
||||
PASS1_set_parameter_type(dsqlScratch, dsqlDelimiter, node, forceVarChar);
|
||||
@ -781,7 +783,8 @@ DmlNode* CountAggNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch*
|
||||
return node;
|
||||
}
|
||||
|
||||
void CountAggNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void CountAggNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->makeLong(0);
|
||||
}
|
||||
@ -862,7 +865,8 @@ DmlNode* SumAggNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* c
|
||||
return node;
|
||||
}
|
||||
|
||||
void SumAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void SumAggNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlArg, nullReplacement);
|
||||
desc->setNullable(true);
|
||||
@ -1110,7 +1114,8 @@ DmlNode* MaxMinAggNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch
|
||||
return node;
|
||||
}
|
||||
|
||||
void MaxMinAggNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void MaxMinAggNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlArg, nullReplacement);
|
||||
desc->setNullable(true);
|
||||
|
@ -37,7 +37,8 @@ public:
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
virtual ExprNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
@ -61,9 +62,10 @@ public:
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
|
||||
@ -94,7 +96,8 @@ public:
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -114,7 +117,8 @@ public:
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
|
||||
@ -139,7 +143,8 @@ public:
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
|
||||
|
@ -35,9 +35,11 @@
|
||||
#include "../jrd/blb_proto.h"
|
||||
#include "../jrd/cmp_proto.h"
|
||||
#include "../jrd/cvt_proto.h"
|
||||
#include "../jrd/dpm_proto.h"
|
||||
#include "../jrd/dsc_proto.h"
|
||||
#include "../jrd/evl_proto.h"
|
||||
#include "../jrd/intl_proto.h"
|
||||
#include "../jrd/met_proto.h"
|
||||
#include "../jrd/mov_proto.h"
|
||||
#include "../jrd/pag_proto.h"
|
||||
#include "../jrd/par_proto.h"
|
||||
@ -322,8 +324,8 @@ void ArithmeticNode::setParameterName(dsql_par* parameter) const
|
||||
parameter->par_name = parameter->par_alias = label;
|
||||
}
|
||||
|
||||
bool ArithmeticNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
bool ArithmeticNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlArg1, node, forceVarChar) |
|
||||
PASS1_set_parameter_type(dsqlScratch, dsqlArg2, node, forceVarChar);
|
||||
@ -336,7 +338,8 @@ void ArithmeticNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, dsqlArg2);
|
||||
}
|
||||
|
||||
void ArithmeticNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void ArithmeticNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
dsc desc1, desc2;
|
||||
|
||||
@ -2468,8 +2471,8 @@ void ConcatenateNode::setParameterName(dsql_par* parameter) const
|
||||
parameter->par_name = parameter->par_alias = "CONCATENATION";
|
||||
}
|
||||
|
||||
bool ConcatenateNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
bool ConcatenateNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlArg1, node, forceVarChar) |
|
||||
PASS1_set_parameter_type(dsqlScratch, dsqlArg2, node, forceVarChar);
|
||||
@ -2482,7 +2485,8 @@ void ConcatenateNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, dsqlArg2);
|
||||
}
|
||||
|
||||
void ConcatenateNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void ConcatenateNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
dsc desc1, desc2;
|
||||
|
||||
@ -2719,7 +2723,8 @@ void CurrentDateNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
dsqlScratch->appendUChar(blr_current_date);
|
||||
}
|
||||
|
||||
void CurrentDateNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void CurrentDateNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->dsc_dtype = dtype_sql_date;
|
||||
desc->dsc_sub_type = 0;
|
||||
@ -2818,7 +2823,8 @@ void CurrentTimeNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
}
|
||||
}
|
||||
|
||||
void CurrentTimeNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void CurrentTimeNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->dsc_dtype = dtype_sql_time;
|
||||
desc->dsc_sub_type = 0;
|
||||
@ -2928,7 +2934,8 @@ void CurrentTimeStampNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
}
|
||||
}
|
||||
|
||||
void CurrentTimeStampNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void CurrentTimeStampNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/,
|
||||
dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->dsc_dtype = dtype_timestamp;
|
||||
desc->dsc_sub_type = 0;
|
||||
@ -3019,7 +3026,8 @@ void CurrentRoleNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
dsqlScratch->appendUChar(blr_current_role);
|
||||
}
|
||||
|
||||
void CurrentRoleNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void CurrentRoleNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->dsc_dtype = dtype_varying;
|
||||
desc->dsc_scale = 0;
|
||||
@ -3114,7 +3122,8 @@ void CurrentUserNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
dsqlScratch->appendUChar(blr_user_name);
|
||||
}
|
||||
|
||||
void CurrentUserNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void CurrentUserNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->dsc_dtype = dtype_varying;
|
||||
desc->dsc_scale = 0;
|
||||
@ -3184,6 +3193,160 @@ ValueExprNode* CurrentUserNode::dsqlPass(DsqlCompilerScratch* /*dsqlScratch*/)
|
||||
//--------------------
|
||||
|
||||
|
||||
static RegisterNode<GenIdNode> regGenIdNode(blr_gen_id);
|
||||
|
||||
GenIdNode::GenIdNode(MemoryPool& pool, bool aDialect1, const MetaName& aName, dsql_nod* aArg)
|
||||
: TypedNode<ValueExprNode, ExprNode::TYPE_GEN_ID>(pool),
|
||||
dialect1(aDialect1),
|
||||
name(pool, aName),
|
||||
dsqlArg(aArg),
|
||||
arg(NULL),
|
||||
id(0)
|
||||
{
|
||||
addChildNode(dsqlArg, arg);
|
||||
}
|
||||
|
||||
DmlNode* GenIdNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR /*blrOp*/)
|
||||
{
|
||||
MetaName name;
|
||||
PAR_name(csb, name);
|
||||
|
||||
const SLONG id = MET_lookup_generator(tdbb, name.c_str());
|
||||
if (id < 0)
|
||||
PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
|
||||
|
||||
if (csb->csb_g_flags & csb_get_dependencies)
|
||||
{
|
||||
CompilerScratch::Dependency dependency(obj_generator);
|
||||
dependency.number = id;
|
||||
csb->csb_dependencies.push(dependency);
|
||||
}
|
||||
|
||||
GenIdNode* node = FB_NEW(pool) GenIdNode(pool, (csb->csb_g_flags & csb_blr_version4), name);
|
||||
node->id = id;
|
||||
node->arg = PAR_parse_node(tdbb, csb, VALUE);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void GenIdNode::print(string& text, Array<dsql_nod*>& nodes) const
|
||||
{
|
||||
text.printf("GenIdNode %s (%d)", name.c_str(), (dialect1 ? 1 : 3));
|
||||
ExprNode::print(text, nodes);
|
||||
}
|
||||
|
||||
ValueExprNode* GenIdNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
return FB_NEW(getPool()) GenIdNode(getPool(), dialect1, name,
|
||||
PASS1_node(dsqlScratch, dsqlArg));
|
||||
}
|
||||
|
||||
void GenIdNode::setParameterName(dsql_par* parameter) const
|
||||
{
|
||||
parameter->par_name = parameter->par_alias = "GEN_ID";
|
||||
}
|
||||
|
||||
bool GenIdNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlArg, node, forceVarChar);
|
||||
}
|
||||
|
||||
void GenIdNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
dsqlScratch->appendUChar(blr_gen_id);
|
||||
dsqlScratch->appendNullString(name.c_str());
|
||||
GEN_expr(dsqlScratch, dsqlArg);
|
||||
}
|
||||
|
||||
void GenIdNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
dsc desc1;
|
||||
MAKE_desc(dsqlScratch, &desc1, dsqlArg, NULL);
|
||||
|
||||
if (dialect1)
|
||||
desc->makeLong(0);
|
||||
else
|
||||
desc->makeInt64(0);
|
||||
|
||||
desc->setNullable(true);
|
||||
}
|
||||
|
||||
void GenIdNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||
{
|
||||
if (dialect1)
|
||||
desc->makeLong(0);
|
||||
else
|
||||
desc->makeInt64(0);
|
||||
}
|
||||
|
||||
ValueExprNode* GenIdNode::copy(thread_db* tdbb, NodeCopier& copier)
|
||||
{
|
||||
GenIdNode* node = FB_NEW(*tdbb->getDefaultPool()) GenIdNode(*tdbb->getDefaultPool(),
|
||||
dialect1, name);
|
||||
node->id = id;
|
||||
node->arg = copier.copy(tdbb, arg);
|
||||
return node;
|
||||
}
|
||||
|
||||
bool GenIdNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
|
||||
{
|
||||
if (!ExprNode::dsqlMatch(other, ignoreMapCast))
|
||||
return false;
|
||||
|
||||
const GenIdNode* o = other->as<GenIdNode>();
|
||||
fb_assert(o)
|
||||
|
||||
return dialect1 == o->dialect1 && name == o->name;
|
||||
}
|
||||
|
||||
bool GenIdNode::expressionEqual(thread_db* tdbb, CompilerScratch* csb, /*const*/ ExprNode* other,
|
||||
USHORT stream)
|
||||
{
|
||||
GenIdNode* otherNode = other->as<GenIdNode>();
|
||||
return otherNode && dialect1 == otherNode->dialect1 && id == otherNode->id;
|
||||
}
|
||||
|
||||
ExprNode* GenIdNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
ExprNode::pass2(tdbb, csb);
|
||||
|
||||
dsc desc;
|
||||
getDesc(tdbb, csb, &desc);
|
||||
node->nod_impure = CMP_impure(csb, sizeof(impure_value));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
dsc* GenIdNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
{
|
||||
request->req_flags &= ~req_null;
|
||||
|
||||
impure_value* const impure = request->getImpure<impure_value>(node->nod_impure);
|
||||
const dsc* value = EVL_expr(tdbb, arg);
|
||||
|
||||
if (request->req_flags & req_null)
|
||||
return NULL;
|
||||
|
||||
if (dialect1)
|
||||
{
|
||||
SLONG temp = (SLONG) DPM_gen_id(tdbb, id, false, MOV_get_int64(value, 0));
|
||||
impure->make_long(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
SINT64 temp = DPM_gen_id(tdbb, id, false, MOV_get_int64(value, 0));
|
||||
impure->make_int64(temp);
|
||||
}
|
||||
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
static RegisterNode<InternalInfoNode> regInternalInfoNode(blr_internal_info);
|
||||
|
||||
// CVC: If this list changes, gpre will need to be updated
|
||||
@ -3243,7 +3406,8 @@ void InternalInfoNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, dsqlArg);
|
||||
}
|
||||
|
||||
void InternalInfoNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void InternalInfoNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
InfoType infoType = static_cast<InfoType>(dsqlArg->getSlong());
|
||||
|
||||
@ -3434,8 +3598,8 @@ void NegateNode::setParameterName(dsql_par* parameter) const
|
||||
}
|
||||
}
|
||||
|
||||
bool NegateNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
bool NegateNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlArg, node, forceVarChar);
|
||||
}
|
||||
@ -3451,7 +3615,8 @@ void NegateNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
}
|
||||
}
|
||||
|
||||
void NegateNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void NegateNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlArg, nullReplacement);
|
||||
|
||||
@ -3758,7 +3923,8 @@ void OverNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, dsqlAggExpr);
|
||||
}
|
||||
|
||||
void OverNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void OverNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlAggExpr, nullReplacement);
|
||||
desc->setNullable(true);
|
||||
@ -3793,6 +3959,356 @@ ValueExprNode* OverNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
//--------------------
|
||||
|
||||
|
||||
static RegisterNode<ParameterNode> regParameterNode(blr_parameter);
|
||||
static RegisterNode<ParameterNode> regParameterNode2(blr_parameter2);
|
||||
static RegisterNode<ParameterNode> regParameterNode3(blr_parameter3);
|
||||
|
||||
ParameterNode::ParameterNode(MemoryPool& pool)
|
||||
: TypedNode<ValueExprNode, ExprNode::TYPE_PARAMETER>(pool),
|
||||
dsqlParameterIndex(0),
|
||||
dsqlParameter(NULL),
|
||||
message(NULL),
|
||||
argNumber(0),
|
||||
argFlag(NULL),
|
||||
argIndicator(NULL),
|
||||
argInfo(NULL)
|
||||
{
|
||||
addChildNode(argFlag);
|
||||
addChildNode(argIndicator);
|
||||
}
|
||||
|
||||
DmlNode* ParameterNode::parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp)
|
||||
{
|
||||
jrd_nod* message = NULL;
|
||||
USHORT n = (USHORT) csb->csb_blr_reader.getByte();
|
||||
|
||||
if (n >= csb->csb_rpt.getCount() || !(message = csb->csb_rpt[n].csb_message))
|
||||
PAR_error(csb, Arg::Gds(isc_badmsgnum));
|
||||
|
||||
ParameterNode* node = FB_NEW(pool) ParameterNode(pool);
|
||||
|
||||
node->message = message;
|
||||
node->argNumber = csb->csb_blr_reader.getWord();
|
||||
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
|
||||
if (node->argNumber >= format->fmt_count)
|
||||
PAR_error(csb, Arg::Gds(isc_badparnum));
|
||||
|
||||
if (blrOp != blr_parameter)
|
||||
{
|
||||
ParameterNode* flagNode = FB_NEW(pool) ParameterNode(pool);
|
||||
flagNode->message = message;
|
||||
flagNode->argNumber = csb->csb_blr_reader.getWord();
|
||||
|
||||
if (flagNode->argNumber >= format->fmt_count)
|
||||
PAR_error(csb, Arg::Gds(isc_badparnum));
|
||||
|
||||
node->argFlag = PAR_make_node(tdbb, 1);
|
||||
node->argFlag->nod_type = nod_class_exprnode_jrd;
|
||||
node->argFlag->nod_count = 0;
|
||||
node->argFlag->nod_arg[0] = reinterpret_cast<jrd_nod*>(flagNode);
|
||||
}
|
||||
|
||||
if (blrOp == blr_parameter3)
|
||||
{
|
||||
ParameterNode* indicatorNode = FB_NEW(pool) ParameterNode(pool);
|
||||
indicatorNode->message = message;
|
||||
indicatorNode->argNumber = csb->csb_blr_reader.getWord();
|
||||
|
||||
if (indicatorNode->argNumber >= format->fmt_count)
|
||||
PAR_error(csb, Arg::Gds(isc_badparnum));
|
||||
|
||||
node->argIndicator = PAR_make_node(tdbb, 1);
|
||||
node->argIndicator->nod_type = nod_class_exprnode_jrd;
|
||||
node->argIndicator->nod_count = 0;
|
||||
node->argIndicator->nod_arg[0] = reinterpret_cast<jrd_nod*>(indicatorNode);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void ParameterNode::print(string& text, Array<dsql_nod*>& nodes) const
|
||||
{
|
||||
text = "ParameterNode";
|
||||
ExprNode::print(text, nodes);
|
||||
}
|
||||
|
||||
ValueExprNode* ParameterNode::dsqlPass(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
if (dsqlScratch->isPsql())
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
Arg::Gds(isc_dsql_command_err));
|
||||
}
|
||||
|
||||
dsql_msg* tempMsg = dsqlParameter ?
|
||||
dsqlParameter->par_message : dsqlScratch->getStatement()->getSendMsg();
|
||||
|
||||
ParameterNode* node = FB_NEW(getPool()) ParameterNode(getPool());
|
||||
node->dsqlParameter = MAKE_parameter(tempMsg, true, true, dsqlParameterIndex, NULL);
|
||||
node->dsqlParameterIndex = dsqlParameterIndex;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
bool ParameterNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
if (!node)
|
||||
thisNode->nod_desc.makeNullString();
|
||||
else
|
||||
{
|
||||
MAKE_desc(dsqlScratch, &thisNode->nod_desc, node, NULL);
|
||||
|
||||
if (tdbb->getCharSet() != CS_NONE && tdbb->getCharSet() != CS_BINARY)
|
||||
{
|
||||
const USHORT fromCharSet = thisNode->nod_desc.getCharSet();
|
||||
const USHORT toCharSet = (fromCharSet == CS_NONE || fromCharSet == CS_BINARY) ?
|
||||
fromCharSet : tdbb->getCharSet();
|
||||
|
||||
if (thisNode->nod_desc.dsc_dtype <= dtype_any_text)
|
||||
{
|
||||
int diff = 0;
|
||||
|
||||
switch (thisNode->nod_desc.dsc_dtype)
|
||||
{
|
||||
case dtype_varying:
|
||||
diff = sizeof(USHORT);
|
||||
break;
|
||||
case dtype_cstring:
|
||||
diff = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
thisNode->nod_desc.dsc_length -= diff;
|
||||
|
||||
if (toCharSet != fromCharSet)
|
||||
{
|
||||
const USHORT fromCharSetBPC = METD_get_charset_bpc(
|
||||
dsqlScratch->getTransaction(), fromCharSet);
|
||||
const USHORT toCharSetBPC = METD_get_charset_bpc(
|
||||
dsqlScratch->getTransaction(), toCharSet);
|
||||
|
||||
thisNode->nod_desc.setTextType(INTL_CS_COLL_TO_TTYPE(toCharSet,
|
||||
(fromCharSet == toCharSet ? INTL_GET_COLLATE(&thisNode->nod_desc) : 0)));
|
||||
|
||||
thisNode->nod_desc.dsc_length = UTLD_char_length_to_byte_length(
|
||||
thisNode->nod_desc.dsc_length / fromCharSetBPC, toCharSetBPC);
|
||||
}
|
||||
|
||||
thisNode->nod_desc.dsc_length += diff;
|
||||
}
|
||||
else if (thisNode->nod_desc.dsc_dtype == dtype_blob &&
|
||||
thisNode->nod_desc.dsc_sub_type == isc_blob_text &&
|
||||
fromCharSet != CS_NONE && fromCharSet != CS_BINARY)
|
||||
{
|
||||
thisNode->nod_desc.setTextType(toCharSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dsqlParameter)
|
||||
{
|
||||
dsqlParameter = MAKE_parameter(dsqlScratch->getStatement()->getSendMsg(), true, true,
|
||||
dsqlParameterIndex, NULL);
|
||||
dsqlParameterIndex = dsqlParameter->par_index;
|
||||
}
|
||||
|
||||
// In case of RETURNING in MERGE and UPDATE OR INSERT, a single parameter is used in
|
||||
// more than one place. So we save it to use below.
|
||||
dsc oldDesc = dsqlParameter->par_desc;
|
||||
bool hasOldDesc = dsqlParameter->par_node != NULL;
|
||||
|
||||
dsqlParameter->par_desc = thisNode->nod_desc;
|
||||
dsqlParameter->par_node = thisNode;
|
||||
|
||||
// Parameters should receive precisely the data that the user
|
||||
// passes in. Therefore for text strings lets use varying
|
||||
// strings to insure that we don't add trailing blanks.
|
||||
|
||||
// However, there are situations this leads to problems - so
|
||||
// we use the forceVarChar parameter to prevent this
|
||||
// datatype assumption from occuring.
|
||||
|
||||
if (forceVarChar)
|
||||
{
|
||||
if (dsqlParameter->par_desc.dsc_dtype == dtype_text)
|
||||
{
|
||||
dsqlParameter->par_desc.dsc_dtype = dtype_varying;
|
||||
// The error msgs is inaccurate, but causing dsc_length
|
||||
// to be outsise range can be worse.
|
||||
if (dsqlParameter->par_desc.dsc_length > MAX_COLUMN_SIZE - sizeof(USHORT))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
//Arg::Gds(isc_dsql_datatype_err)
|
||||
Arg::Gds(isc_imp_exc));
|
||||
//Arg::Gds(isc_field_name) << Arg::Str(parameter->par_name)
|
||||
}
|
||||
|
||||
dsqlParameter->par_desc.dsc_length += sizeof(USHORT);
|
||||
}
|
||||
else if (dsqlParameter->par_desc.dsc_dtype > dtype_any_text)
|
||||
{
|
||||
const USHORT toCharSetBPC = METD_get_charset_bpc(
|
||||
dsqlScratch->getTransaction(), tdbb->getCharSet());
|
||||
|
||||
// The LIKE & similar parameters must be varchar type
|
||||
// strings - so force this parameter to be varchar
|
||||
// and take a guess at a good length for it.
|
||||
dsqlParameter->par_desc.dsc_dtype = dtype_varying;
|
||||
dsqlParameter->par_desc.dsc_length = LIKE_PARAM_LEN * toCharSetBPC + sizeof(USHORT);
|
||||
dsqlParameter->par_desc.dsc_sub_type = 0;
|
||||
dsqlParameter->par_desc.dsc_scale = 0;
|
||||
dsqlParameter->par_desc.dsc_ttype() = ttype_dynamic;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOldDesc)
|
||||
{
|
||||
dsc thisDesc = dsqlParameter->par_desc;
|
||||
const dsc* args[] = {&oldDesc, &thisDesc};
|
||||
DSqlDataTypeUtil(dsqlScratch).makeFromList(&dsqlParameter->par_desc,
|
||||
dsqlParameter->par_name.c_str(), 2, args);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParameterNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
{
|
||||
GEN_parameter(dsqlScratch, dsqlParameter);
|
||||
}
|
||||
|
||||
void ParameterNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
// We don't actually know the datatype of a parameter -
|
||||
// we have to guess it based on the context that the
|
||||
// parameter appears in. (This is done is pass1.c::set_parameter_type())
|
||||
// However, a parameter can appear as part of an expression.
|
||||
// As MAKE_desc is used for both determination of parameter
|
||||
// types and for expression type checking, we just continue.
|
||||
|
||||
if (thisNode->nod_desc.dsc_dtype)
|
||||
*desc = thisNode->nod_desc;
|
||||
}
|
||||
|
||||
bool ParameterNode::dsqlMatch(const ExprNode* other, bool ignoreMapCast) const
|
||||
{
|
||||
const ParameterNode* o = other->as<ParameterNode>();
|
||||
|
||||
return o && dsqlParameter->par_index == o->dsqlParameter->par_index;
|
||||
}
|
||||
|
||||
void ParameterNode::getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc)
|
||||
{
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
*desc = format->fmt_desc[argNumber];
|
||||
}
|
||||
|
||||
ValueExprNode* ParameterNode::copy(thread_db* tdbb, NodeCopier& copier)
|
||||
{
|
||||
if (copier.remapArgument())
|
||||
return this;
|
||||
|
||||
ParameterNode* node = FB_NEW(*tdbb->getDefaultPool()) ParameterNode(*tdbb->getDefaultPool());
|
||||
node->argNumber = argNumber;
|
||||
|
||||
// dimitr: IMPORTANT!!!
|
||||
// nod_message copying must be done in the only place
|
||||
// (the nod_procedure code). Hence we don't call
|
||||
// copy() here to keep argument->nod_arg[e_arg_message]
|
||||
// and procedure->nod_arg[e_prc_in_msg] in sync. The
|
||||
// message is passed to copy() as a parameter. If the
|
||||
// passed message is NULL, it means nod_argument is
|
||||
// cloned outside nod_procedure (e.g. in the optimizer)
|
||||
// and we must keep the input message.
|
||||
// ASF: We should only use "message" if its number matches the number
|
||||
// in nod_argument. If it don't, it may be an input parameter cloned
|
||||
// in RseBoolNode::convertNeqAllToNotAny - see CORE-3094.
|
||||
|
||||
if (copier.message &&
|
||||
(IPTR) copier.message->nod_arg[e_msg_number] == (IPTR) message->nod_arg[e_msg_number])
|
||||
{
|
||||
node->message = copier.message;
|
||||
}
|
||||
else
|
||||
node->message = message;
|
||||
|
||||
node->argFlag = copier.copy(tdbb, argFlag);
|
||||
node->argIndicator = copier.copy(tdbb, argIndicator);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
ExprNode* ParameterNode::pass2(thread_db* tdbb, CompilerScratch* csb)
|
||||
{
|
||||
argInfo = CMP_pass2_validation(tdbb, csb,
|
||||
Item(Item::TYPE_PARAMETER, (IPTR) message->nod_arg[e_msg_number], argNumber));
|
||||
|
||||
ExprNode::pass2(tdbb, csb);
|
||||
|
||||
dsc desc;
|
||||
getDesc(tdbb, csb, &desc);
|
||||
node->nod_impure = CMP_impure(csb, (node->nod_flags & nod_value) ?
|
||||
sizeof(impure_value_ex) : sizeof(dsc));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
dsc* ParameterNode::execute(thread_db* tdbb, jrd_req* request) const
|
||||
{
|
||||
impure_value* const impure = request->getImpure<impure_value>(node->nod_impure);
|
||||
request->req_flags &= ~req_null;
|
||||
|
||||
const dsc* desc;
|
||||
|
||||
if (argFlag)
|
||||
{
|
||||
desc = EVL_expr(tdbb, argFlag);
|
||||
if (MOV_get_long(desc, 0))
|
||||
request->req_flags |= req_null;
|
||||
}
|
||||
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
desc = &format->fmt_desc[argNumber];
|
||||
|
||||
impure->vlu_desc.dsc_address = request->getImpure<UCHAR>(
|
||||
message->nod_impure + (IPTR) desc->dsc_address);
|
||||
impure->vlu_desc.dsc_dtype = desc->dsc_dtype;
|
||||
impure->vlu_desc.dsc_length = desc->dsc_length;
|
||||
impure->vlu_desc.dsc_scale = desc->dsc_scale;
|
||||
impure->vlu_desc.dsc_sub_type = desc->dsc_sub_type;
|
||||
|
||||
if (impure->vlu_desc.dsc_dtype == dtype_text)
|
||||
INTL_adjust_text_descriptor(tdbb, &impure->vlu_desc);
|
||||
|
||||
USHORT* impure_flags = request->getImpure<USHORT>(
|
||||
(IPTR) message->nod_arg[e_msg_impure_flags] +
|
||||
(sizeof(USHORT) * argNumber));
|
||||
|
||||
if (!(*impure_flags & VLU_checked))
|
||||
{
|
||||
if (argInfo)
|
||||
{
|
||||
EVL_validate(tdbb,
|
||||
Item(Item::TYPE_PARAMETER, (IPTR) message->nod_arg[e_msg_number], argNumber),
|
||||
argInfo, &impure->vlu_desc, request->req_flags & req_null);
|
||||
}
|
||||
|
||||
*impure_flags |= VLU_checked;
|
||||
}
|
||||
|
||||
return (request->req_flags & req_null) ? NULL : &impure->vlu_desc;
|
||||
}
|
||||
|
||||
|
||||
//--------------------
|
||||
|
||||
|
||||
static RegisterNode<SubstringSimilarNode> regSubstringSimilarNode(blr_substring_similar);
|
||||
|
||||
SubstringSimilarNode::SubstringSimilarNode(MemoryPool& pool, dsql_nod* aExpr, dsql_nod* aPattern,
|
||||
@ -3831,8 +4347,8 @@ void SubstringSimilarNode::setParameterName(dsql_par* parameter) const
|
||||
parameter->par_name = parameter->par_alias = "SUBSTRING";
|
||||
}
|
||||
|
||||
bool SubstringSimilarNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
bool SubstringSimilarNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlExpr, node, forceVarChar) |
|
||||
PASS1_set_parameter_type(dsqlScratch, dsqlPattern, node, forceVarChar) |
|
||||
@ -3847,7 +4363,8 @@ void SubstringSimilarNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, dsqlEscape);
|
||||
}
|
||||
|
||||
void SubstringSimilarNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void SubstringSimilarNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlExpr, nullReplacement);
|
||||
desc->setNullable(true);
|
||||
@ -4085,7 +4602,8 @@ void SysFuncCallNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, *ptr);
|
||||
}
|
||||
|
||||
void SysFuncCallNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void SysFuncCallNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
Array<const dsc*> argsArray;
|
||||
|
||||
@ -4324,7 +4842,8 @@ void UdfCallNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, *ptr);
|
||||
}
|
||||
|
||||
void UdfCallNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void UdfCallNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->dsc_dtype = static_cast<UCHAR>(dsqlFunction->udf_dtype);
|
||||
desc->dsc_length = dsqlFunction->udf_length;
|
||||
@ -4520,8 +5039,8 @@ void ValueIfNode::setParameterName(dsql_par* parameter) const
|
||||
parameter->par_name = parameter->par_alias = "CASE";
|
||||
}
|
||||
|
||||
bool ValueIfNode::setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const
|
||||
bool ValueIfNode::setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar)
|
||||
{
|
||||
return PASS1_set_parameter_type(dsqlScratch, dsqlTrueValue, node, forceVarChar) |
|
||||
PASS1_set_parameter_type(dsqlScratch, dsqlFalseValue, node, forceVarChar);
|
||||
@ -4535,7 +5054,8 @@ void ValueIfNode::genBlr(DsqlCompilerScratch* dsqlScratch)
|
||||
GEN_expr(dsqlScratch, dsqlFalseValue);
|
||||
}
|
||||
|
||||
void ValueIfNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void ValueIfNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
Array<const dsc*> args;
|
||||
|
||||
|
@ -31,6 +31,8 @@ class SysFunction;
|
||||
|
||||
namespace Jrd {
|
||||
|
||||
struct ItemInfo;
|
||||
|
||||
|
||||
class ArithmeticNode : public TypedNode<ValueExprNode, ExprNode::TYPE_ARITHMETIC>
|
||||
{
|
||||
@ -43,10 +45,11 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -97,10 +100,11 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -128,7 +132,8 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -152,7 +157,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -179,7 +185,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -205,7 +212,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -228,7 +236,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -237,6 +246,50 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class GenIdNode : public TypedNode<ValueExprNode, ExprNode::TYPE_GEN_ID>
|
||||
{
|
||||
public:
|
||||
GenIdNode(MemoryPool& pool, bool aDialect1, const Firebird::MetaName& aName,
|
||||
dsql_nod* aArg = NULL);
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual bool jrdVisit(JrdNodeVisitor& visitor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool jrdUnmappedNodeGetter(UnmappedNodeGetter& visitor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
virtual bool dsqlMatch(const ExprNode* other, bool ignoreMapCast) const;
|
||||
virtual bool expressionEqual(thread_db* tdbb, CompilerScratch* csb, /*const*/ ExprNode* other,
|
||||
USHORT stream) /*const*/;
|
||||
virtual ExprNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual dsc* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
|
||||
public:
|
||||
bool dialect1;
|
||||
Firebird::MetaName name;
|
||||
dsql_nod* dsqlArg;
|
||||
NestConst<jrd_nod> arg;
|
||||
SLONG id;
|
||||
};
|
||||
|
||||
|
||||
class InternalInfoNode : public TypedNode<ValueExprNode, ExprNode::TYPE_INTERNAL_INFO>
|
||||
{
|
||||
public:
|
||||
@ -270,7 +323,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -293,10 +347,11 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -328,7 +383,8 @@ public:
|
||||
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -341,6 +397,58 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class ParameterNode : public TypedNode<ValueExprNode, ExprNode::TYPE_PARAMETER>
|
||||
{
|
||||
private:
|
||||
// CVC: This is a guess for the length of the parameter for LIKE and others, when the
|
||||
// original dtype isn't string and force_varchar is true.
|
||||
static const int LIKE_PARAM_LEN = 30;
|
||||
|
||||
public:
|
||||
ParameterNode(MemoryPool& pool);
|
||||
|
||||
static DmlNode* parse(thread_db* tdbb, MemoryPool& pool, CompilerScratch* csb, UCHAR blrOp);
|
||||
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
|
||||
virtual void setParameterName(dsql_par* parameter) const
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual bool dsqlMatch(const ExprNode* other, bool ignoreMapCast) const;
|
||||
|
||||
virtual bool jrdVisit(JrdNodeVisitor& visitor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool jrdUnmappedNodeGetter(UnmappedNodeGetter& visitor)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
virtual ExprNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
virtual dsc* execute(thread_db* tdbb, jrd_req* request) const;
|
||||
|
||||
public:
|
||||
USHORT dsqlParameterIndex;
|
||||
dsql_par* dsqlParameter;
|
||||
NestConst<jrd_nod> message;
|
||||
USHORT argNumber;
|
||||
NestConst<jrd_nod> argFlag;
|
||||
NestConst<jrd_nod> argIndicator;
|
||||
NestConst<ItemInfo> argInfo;
|
||||
};
|
||||
|
||||
|
||||
class SubstringSimilarNode : public TypedNode<ValueExprNode, ExprNode::TYPE_SUBSTRING_SIMILAR>
|
||||
{
|
||||
public:
|
||||
@ -352,10 +460,11 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -385,7 +494,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -416,7 +526,8 @@ public:
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
@ -449,10 +560,11 @@ public:
|
||||
virtual void print(Firebird::string& text, Firebird::Array<dsql_nod*>& nodes) const;
|
||||
virtual ValueExprNode* dsqlPass(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void setParameterName(dsql_par* parameter) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch,
|
||||
dsql_nod* node, bool forceVarChar) const;
|
||||
virtual bool setParameterType(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode,
|
||||
dsql_nod* node, bool forceVarChar);
|
||||
virtual void genBlr(DsqlCompilerScratch* dsqlScratch);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
|
||||
virtual bool jrdPossibleUnknownFinder(PossibleUnknownFinder& /*visitor*/)
|
||||
{
|
||||
|
@ -264,11 +264,13 @@ public:
|
||||
TYPE_CURRENT_TIMESTAMP,
|
||||
TYPE_CURRENT_ROLE,
|
||||
TYPE_CURRENT_USER,
|
||||
TYPE_GEN_ID,
|
||||
TYPE_INTERNAL_INFO,
|
||||
TYPE_MISSING_BOOL,
|
||||
TYPE_NEGATE,
|
||||
TYPE_NOT_BOOL,
|
||||
TYPE_OVER,
|
||||
TYPE_PARAMETER,
|
||||
TYPE_RSE_BOOL,
|
||||
TYPE_SUBSTRING_SIMILAR,
|
||||
TYPE_SYSFUNC_CALL,
|
||||
@ -415,6 +417,11 @@ protected:
|
||||
dsqlChildNodes.add(&dsqlNode);
|
||||
}
|
||||
|
||||
void addChildNode(const JrdNode& jrdNode)
|
||||
{
|
||||
jrdChildNodes.add(jrdNode);
|
||||
}
|
||||
|
||||
public:
|
||||
const Type type;
|
||||
const char* dsqlCompatDialectVerb;
|
||||
@ -483,14 +490,15 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual bool setParameterType(DsqlCompilerScratch* /*dsqlScratch*/,
|
||||
dsql_nod* /*node*/, bool /*forceVarChar*/) const
|
||||
virtual bool setParameterType(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/,
|
||||
dsql_nod* /*node*/, bool /*forceVarChar*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void setParameterName(dsql_par* parameter) const = 0;
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement) = 0;
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement) = 0;
|
||||
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc) = 0;
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier) = 0;
|
||||
|
@ -221,7 +221,7 @@ private:
|
||||
|
||||
const TEXT* lex_position();
|
||||
dsql_nod* make_list (dsql_nod* node);
|
||||
dsql_nod* make_parameter();
|
||||
ParameterNode* make_parameter();
|
||||
dsql_nod* make_node(Dsql::nod_t type, int count, ...);
|
||||
dsql_nod* makeClassNode(ExprNode* node);
|
||||
dsql_nod* makeClassNode(DdlNode* node);
|
||||
|
@ -457,7 +457,6 @@ public:
|
||||
return NodeCopier(csb, remap).copy(tdbb, input);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool remapArgument()
|
||||
{
|
||||
return false;
|
||||
@ -498,7 +497,6 @@ inline bool DsqlNodeVisitor<T, T2>::visitChildren(T node)
|
||||
}
|
||||
|
||||
case nod_constant:
|
||||
case nod_parameter:
|
||||
case nod_variable:
|
||||
case nod_null:
|
||||
case nod_dom_value:
|
||||
@ -516,8 +514,6 @@ inline bool DsqlNodeVisitor<T, T2>::visitChildren(T node)
|
||||
ret |= visit(&node->nod_arg[e_order_field]);
|
||||
break;
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
case nod_cast:
|
||||
if (node->nod_count == 2)
|
||||
ret |= visit(&node->nod_arg[1]);
|
||||
|
@ -99,7 +99,8 @@ DenseRankWinNode::DenseRankWinNode(MemoryPool& pool)
|
||||
jrdChildNodes.clear();
|
||||
}
|
||||
|
||||
void DenseRankWinNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void DenseRankWinNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->makeInt64(0);
|
||||
}
|
||||
@ -153,7 +154,8 @@ RankWinNode::RankWinNode(MemoryPool& pool)
|
||||
jrdChildNodes.clear();
|
||||
}
|
||||
|
||||
void RankWinNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void RankWinNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->makeInt64(0);
|
||||
}
|
||||
@ -224,7 +226,8 @@ RowNumberWinNode::RowNumberWinNode(MemoryPool& pool)
|
||||
jrdChildNodes.clear();
|
||||
}
|
||||
|
||||
void RowNumberWinNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsc* desc, dsql_nod* /*nullReplacement*/)
|
||||
void RowNumberWinNode::make(DsqlCompilerScratch* /*dsqlScratch*/, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* /*nullReplacement*/)
|
||||
{
|
||||
desc->makeInt64(0);
|
||||
}
|
||||
@ -289,7 +292,8 @@ LagLeadWinNode::LagLeadWinNode(MemoryPool& pool, const AggInfo& aAggInfo, int aD
|
||||
addChildNode(dsqlOutExpr, outExpr);
|
||||
}
|
||||
|
||||
void LagLeadWinNode::make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement)
|
||||
void LagLeadWinNode::make(DsqlCompilerScratch* dsqlScratch, dsql_nod* /*thisNode*/, dsc* desc,
|
||||
dsql_nod* nullReplacement)
|
||||
{
|
||||
MAKE_desc(dsqlScratch, desc, dsqlArg, nullReplacement);
|
||||
desc->setNullable(true);
|
||||
|
@ -36,7 +36,8 @@ class DenseRankWinNode : public WinFuncNode
|
||||
public:
|
||||
explicit DenseRankWinNode(MemoryPool& pool);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
|
||||
@ -54,7 +55,8 @@ class RankWinNode : public WinFuncNode
|
||||
public:
|
||||
explicit RankWinNode(MemoryPool& pool);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
virtual ExprNode* pass2(thread_db* tdbb, CompilerScratch* csb);
|
||||
@ -76,7 +78,8 @@ class RowNumberWinNode : public WinFuncNode
|
||||
public:
|
||||
explicit RowNumberWinNode(MemoryPool& pool);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
virtual ValueExprNode* copy(thread_db* tdbb, NodeCopier& copier);
|
||||
|
||||
@ -102,7 +105,8 @@ public:
|
||||
explicit LagLeadWinNode(MemoryPool& pool, const AggInfo& aAggInfo, int aDirection,
|
||||
dsql_nod* aArg = NULL, dsql_nod* aRows = NULL, dsql_nod* aOutExpr = NULL);
|
||||
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* nullReplacement);
|
||||
virtual void make(DsqlCompilerScratch* dsqlScratch, dsql_nod* thisNode, dsc* desc,
|
||||
dsql_nod* nullReplacement);
|
||||
virtual void getDesc(thread_db* tdbb, CompilerScratch* csb, dsc* desc);
|
||||
|
||||
virtual void aggInit(thread_db* tdbb, jrd_req* request) const;
|
||||
|
@ -1292,7 +1292,7 @@ static SSHORT filter_sub_type(dsql_req* request, const dsql_nod* node)
|
||||
if (node->nod_type == nod_constant)
|
||||
return (SSHORT) node->getSlong();
|
||||
|
||||
const dsql_par* parameter = (dsql_par*) node->nod_arg[e_par_parameter];
|
||||
const dsql_par* parameter = (dsql_par*) ExprNode::as<ParameterNode>(node)->dsqlParameter;
|
||||
const dsql_par* null = parameter->par_null;
|
||||
dsc desc;
|
||||
|
||||
|
@ -69,11 +69,9 @@ static void gen_constant(DsqlCompilerScratch*, const dsc*, bool);
|
||||
static void gen_error_condition(DsqlCompilerScratch*, const dsql_nod*);
|
||||
static void gen_exec_stmt(DsqlCompilerScratch* dsqlScratch, const dsql_nod* node);
|
||||
static void gen_field(DsqlCompilerScratch*, const dsql_ctx*, const dsql_fld*, dsql_nod*);
|
||||
static void gen_gen_id(DsqlCompilerScratch*, const dsql_nod*);
|
||||
static void gen_join_rse(DsqlCompilerScratch*, const dsql_nod*);
|
||||
static void gen_map(DsqlCompilerScratch*, dsql_map*);
|
||||
static inline void gen_optional_expr(DsqlCompilerScratch*, const UCHAR code, dsql_nod*);
|
||||
static void gen_parameter(DsqlCompilerScratch*, const dsql_par*);
|
||||
static void gen_plan(DsqlCompilerScratch*, const dsql_nod*);
|
||||
static void gen_relation(DsqlCompilerScratch*, dsql_ctx*);
|
||||
static void gen_searched_case(DsqlCompilerScratch*, const dsql_nod*);
|
||||
@ -294,10 +292,6 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
||||
}
|
||||
return;
|
||||
|
||||
case nod_parameter:
|
||||
gen_parameter(dsqlScratch, (dsql_par*) node->nod_arg[e_par_parameter]);
|
||||
return;
|
||||
|
||||
case nod_relation:
|
||||
gen_relation(dsqlScratch, (dsql_ctx*) node->nod_arg[e_rel_context]);
|
||||
return;
|
||||
@ -329,10 +323,6 @@ void GEN_expr(DsqlCompilerScratch* dsqlScratch, dsql_nod* node)
|
||||
case nod_cast:
|
||||
gen_cast(dsqlScratch, node);
|
||||
return;
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
gen_gen_id(dsqlScratch, node);
|
||||
return;
|
||||
case nod_coalesce:
|
||||
gen_coalesce(dsqlScratch, node);
|
||||
return;
|
||||
@ -1619,26 +1609,6 @@ static void gen_field( DsqlCompilerScratch* dsqlScratch, const dsql_ctx* context
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
gen_gen_id
|
||||
|
||||
@brief Generate BLR for gen_id
|
||||
|
||||
|
||||
@param dsqlScratch
|
||||
@param node
|
||||
|
||||
**/
|
||||
static void gen_gen_id( DsqlCompilerScratch* dsqlScratch, const dsql_nod* node)
|
||||
{
|
||||
dsqlScratch->appendUChar(blr_gen_id);
|
||||
const dsql_str* string = (dsql_str*) node->nod_arg[e_gen_id_name];
|
||||
dsqlScratch->appendNullString(string->str_data);
|
||||
GEN_expr(dsqlScratch, node->nod_arg[e_gen_id_value]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
||||
gen_join_rse
|
||||
@ -1718,18 +1688,8 @@ static void gen_optional_expr(DsqlCompilerScratch* dsqlScratch, const UCHAR code
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
gen_parameter
|
||||
|
||||
@brief Generate a parameter reference.
|
||||
|
||||
|
||||
@param dsqlScratch
|
||||
@param parameter
|
||||
|
||||
**/
|
||||
static void gen_parameter( DsqlCompilerScratch* dsqlScratch, const dsql_par* parameter)
|
||||
// Generate a parameter reference.
|
||||
void GEN_parameter( DsqlCompilerScratch* dsqlScratch, const dsql_par* parameter)
|
||||
{
|
||||
const dsql_msg* message = parameter->par_message;
|
||||
|
||||
@ -2179,7 +2139,7 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse)
|
||||
dsqlScratch->appendUChar(blr_assignment);
|
||||
constant = 1;
|
||||
gen_constant(dsqlScratch, &constant_desc, false);
|
||||
gen_parameter(dsqlScratch, statement->getEof());
|
||||
GEN_parameter(dsqlScratch, statement->getEof());
|
||||
|
||||
for (size_t i = 0; i < message->msg_parameters.getCount(); ++i)
|
||||
{
|
||||
@ -2189,7 +2149,7 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse)
|
||||
{
|
||||
dsqlScratch->appendUChar(blr_assignment);
|
||||
GEN_expr(dsqlScratch, parameter->par_node);
|
||||
gen_parameter(dsqlScratch, parameter);
|
||||
GEN_parameter(dsqlScratch, parameter);
|
||||
}
|
||||
|
||||
if (parameter->par_dbkey_relname.hasData() && paramContexts.get(parameter, context))
|
||||
@ -2197,7 +2157,7 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse)
|
||||
dsqlScratch->appendUChar(blr_assignment);
|
||||
dsqlScratch->appendUChar(blr_dbkey);
|
||||
stuff_context(dsqlScratch, context);
|
||||
gen_parameter(dsqlScratch, parameter);
|
||||
GEN_parameter(dsqlScratch, parameter);
|
||||
}
|
||||
|
||||
if (parameter->par_rec_version_relname.hasData() && paramContexts.get(parameter, context))
|
||||
@ -2205,7 +2165,7 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse)
|
||||
dsqlScratch->appendUChar(blr_assignment);
|
||||
dsqlScratch->appendUChar(blr_record_version);
|
||||
stuff_context(dsqlScratch, context);
|
||||
gen_parameter(dsqlScratch, parameter);
|
||||
GEN_parameter(dsqlScratch, parameter);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2215,7 +2175,7 @@ static void gen_select(DsqlCompilerScratch* dsqlScratch, dsql_nod* rse)
|
||||
dsqlScratch->appendUChar(blr_assignment);
|
||||
constant = 0;
|
||||
gen_constant(dsqlScratch, &constant_desc, false);
|
||||
gen_parameter(dsqlScratch, statement->getEof());
|
||||
GEN_parameter(dsqlScratch, statement->getEof());
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,6 +28,7 @@ void GEN_constant(Jrd::DsqlCompilerScratch* dsqlScratch, Jrd::dsql_nod* node, bo
|
||||
void GEN_descriptor(Jrd::DsqlCompilerScratch* dsqlScratch, const dsc* desc, bool texttype);
|
||||
void GEN_expr(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
void GEN_hidden_variables(Jrd::DsqlCompilerScratch* dsqlScratch, bool inExpression);
|
||||
void GEN_parameter(Jrd::DsqlCompilerScratch*, const Jrd::dsql_par*);
|
||||
void GEN_port(Jrd::DsqlCompilerScratch*, Jrd::dsql_msg*);
|
||||
void GEN_request(Jrd::DsqlCompilerScratch*, Jrd::dsql_nod*);
|
||||
void GEN_rse(Jrd::DsqlCompilerScratch*, const Jrd::dsql_nod*);
|
||||
|
@ -402,7 +402,7 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node, dsql
|
||||
case nod_class_exprnode:
|
||||
{
|
||||
ValueExprNode* exprNode = reinterpret_cast<ValueExprNode*>(node->nod_arg[0]);
|
||||
exprNode->make(dsqlScratch, desc, null_replacement);
|
||||
exprNode->make(dsqlScratch, node, desc, null_replacement);
|
||||
}
|
||||
return;
|
||||
|
||||
@ -545,25 +545,6 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node, dsql
|
||||
}
|
||||
return;
|
||||
|
||||
case nod_gen_id:
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_gen_id_value], NULL);
|
||||
desc->dsc_dtype = dtype_long;
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_scale = 0;
|
||||
desc->dsc_length = sizeof(SLONG);
|
||||
desc->dsc_flags = (desc1.dsc_flags & DSC_nullable);
|
||||
return;
|
||||
|
||||
case nod_gen_id2:
|
||||
MAKE_desc(dsqlScratch, &desc1, node->nod_arg[e_gen_id_value], NULL);
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_scale = 0;
|
||||
desc->dsc_length = sizeof(SINT64);
|
||||
desc->dsc_flags = (desc1.dsc_flags & DSC_nullable);
|
||||
node->nod_flags |= NOD_COMP_DIALECT; // Never checked!
|
||||
return;
|
||||
|
||||
case nod_limit:
|
||||
case nod_rows:
|
||||
if (dsqlScratch->clientDialect <= SQL_DIALECT_V5)
|
||||
@ -624,20 +605,6 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node, dsql
|
||||
desc->dsc_length = sizeof(ULONG);
|
||||
return;
|
||||
|
||||
case nod_parameter:
|
||||
// We don't actually know the datatype of a parameter -
|
||||
// we have to guess it based on the context that the
|
||||
// parameter appears in. (This is done is pass1.c::set_parameter_type())
|
||||
// However, a parameter can appear as part of an expression.
|
||||
// As MAKE_desc is used for both determination of parameter
|
||||
// types and for expression type checking, we just continue.
|
||||
|
||||
if (node->nod_desc.dsc_dtype)
|
||||
{
|
||||
*desc = node->nod_desc;
|
||||
}
|
||||
return;
|
||||
|
||||
case nod_null:
|
||||
// This occurs when SQL statement specifies a literal NULL, eg:
|
||||
// SELECT NULL FROM TABLE1;
|
||||
@ -1252,10 +1219,6 @@ void MAKE_parameter_names(dsql_par* parameter, const dsql_nod* item)
|
||||
name_alias = variable->var_field->fld_name.c_str();
|
||||
break;
|
||||
}
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
name_alias = "GEN_ID";
|
||||
break;
|
||||
case nod_constant:
|
||||
case nod_null:
|
||||
name_alias = "CONSTANT";
|
||||
|
@ -126,7 +126,6 @@ enum nod_t
|
||||
nod_field,
|
||||
nod_dom_value,
|
||||
nod_field_name,
|
||||
nod_parameter,
|
||||
nod_constant,
|
||||
nod_map,
|
||||
nod_alias,
|
||||
@ -142,8 +141,6 @@ enum nod_t
|
||||
nod_upcase,
|
||||
nod_lowcase,
|
||||
nod_collate,
|
||||
nod_gen_id,
|
||||
nod_gen_id2,
|
||||
nod_get_segment, // blobs
|
||||
nod_put_segment,
|
||||
nod_join_inner, // join types
|
||||
@ -261,7 +258,7 @@ enum nod_t
|
||||
* e_<nodename>_count == count of arguments in nod_arg
|
||||
* This is often used as the count of sub-nodes, but there
|
||||
* are cases when non-DSQL_NOD arguments are stuffed into nod_arg
|
||||
* entries. These include nod_udf, nod_gen_id, nod_cast,
|
||||
* entries. These include nod_udf, nod_cast,
|
||||
* & nod_collate.
|
||||
*/
|
||||
enum node_args {
|
||||
@ -358,10 +355,6 @@ enum node_args {
|
||||
e_rows_length,
|
||||
e_rows_count,
|
||||
|
||||
e_par_index = 0, // nod_parameter
|
||||
e_par_parameter,
|
||||
e_par_count,
|
||||
|
||||
e_cur_name = 0, // nod_cursor
|
||||
e_cur_scroll,
|
||||
e_cur_rse,
|
||||
@ -622,7 +615,7 @@ enum node_args {
|
||||
e_filter_module,
|
||||
e_filter_count,
|
||||
|
||||
e_gen_id_name = 0, // Not a DSQL_NOD nod_gen_id
|
||||
e_gen_id_name = 0, // Not a DSQL_NOD nod_set_generator
|
||||
e_gen_id_value,
|
||||
e_gen_id_count,
|
||||
|
||||
|
@ -5318,9 +5318,9 @@ u_constant : u_numeric_constant
|
||||
{ $$ = MAKE_constant ($2, CONSTANT_TIMESTAMP); }
|
||||
;
|
||||
|
||||
parameter : '?'
|
||||
{ $$ = make_parameter (); }
|
||||
;
|
||||
parameter
|
||||
: '?' { $$ = makeClassNode(make_parameter()); }
|
||||
;
|
||||
|
||||
current_user
|
||||
: USER
|
||||
@ -5830,21 +5830,18 @@ decode_pairs
|
||||
|
||||
// next value expression
|
||||
|
||||
next_value_expression : NEXT KW_VALUE FOR symbol_generator_name
|
||||
{
|
||||
if (client_dialect >= SQL_DIALECT_V6_TRANSITION)
|
||||
$$ = make_node (nod_gen_id2, 2, $4, MAKE_const_slong(1));
|
||||
else
|
||||
$$ = make_node (nod_gen_id, 2, $4, MAKE_const_slong(1));
|
||||
}
|
||||
| GEN_ID '(' symbol_generator_name ',' value ')'
|
||||
{
|
||||
if (client_dialect >= SQL_DIALECT_V6_TRANSITION)
|
||||
$$ = make_node (nod_gen_id2, 2, $3, $5);
|
||||
else
|
||||
$$ = make_node (nod_gen_id, 2, $3, $5);
|
||||
}
|
||||
;
|
||||
next_value_expression
|
||||
: NEXT KW_VALUE FOR symbol_generator_name
|
||||
{
|
||||
$$ = makeClassNode(FB_NEW(getPool()) GenIdNode(getPool(),
|
||||
(client_dialect < SQL_DIALECT_V6_TRANSITION), toName($4)));
|
||||
}
|
||||
| GEN_ID '(' symbol_generator_name ',' value ')'
|
||||
{
|
||||
$$ = makeClassNode(FB_NEW(getPool()) GenIdNode(getPool(),
|
||||
(client_dialect < SQL_DIALECT_V6_TRANSITION), toName($3), $5));
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
timestamp_part : YEAR
|
||||
@ -6364,27 +6361,13 @@ dsql_nod* Parser::make_list (dsql_nod* node)
|
||||
}
|
||||
|
||||
|
||||
dsql_nod* Parser::make_parameter()
|
||||
// Make parameter node.
|
||||
ParameterNode* Parser::make_parameter()
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* m a k e _ p a r a m e t e r
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Make parameter node
|
||||
* Any change should also be made to function below
|
||||
*
|
||||
**************************************/
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
dsql_nod* node = FB_NEW_RPT(*tdbb->getDefaultPool(), e_par_count) dsql_nod;
|
||||
node->nod_type = nod_parameter;
|
||||
node->nod_line = (USHORT) lex.lines_bk;
|
||||
node->nod_column = (USHORT) (lex.last_token_bk - lex.line_start_bk + 1);
|
||||
node->nod_count = e_par_count;
|
||||
node->nod_arg[e_par_index] = (dsql_nod*)(IPTR) lex.param_number++;
|
||||
ParameterNode* node = FB_NEW(*tdbb->getDefaultPool()) ParameterNode(*tdbb->getDefaultPool());
|
||||
node->dsqlParameterIndex = lex.param_number++;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
@ -245,11 +245,6 @@ static dsql_nod* process_returning(DsqlCompilerScratch*, dsql_nod*);
|
||||
|
||||
const char* const DB_KEY_STRING = "DB_KEY"; // NTX: pseudo field name
|
||||
|
||||
const int LIKE_PARAM_LEN = 30; // CVC: This is a guess for the length of the
|
||||
// parameter for LIKE and others, when the
|
||||
// original dtype isn't string and force_varchar
|
||||
// is true.
|
||||
|
||||
namespace
|
||||
{
|
||||
class ReturningProcessor
|
||||
@ -1292,13 +1287,6 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
case nod_searched_case:
|
||||
return pass1_searched_case(dsqlScratch, input);
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
node = MAKE_node(input->nod_type, e_gen_id_count);
|
||||
node->nod_arg[e_gen_id_value] = PASS1_node(dsqlScratch, input->nod_arg[e_gen_id_value]);
|
||||
node->nod_arg[e_gen_id_name] = input->nod_arg[e_gen_id_name];
|
||||
return node;
|
||||
|
||||
case nod_collate:
|
||||
sub1 = PASS1_node(dsqlScratch, input->nod_arg[e_coll_source]);
|
||||
node = pass1_collate(dsqlScratch, sub1, (dsql_str*) input->nod_arg[e_coll_target]);
|
||||
@ -1496,27 +1484,6 @@ dsql_nod* PASS1_node(DsqlCompilerScratch* dsqlScratch, dsql_nod* input)
|
||||
case nod_constant:
|
||||
return pass1_constant(dsqlScratch, input);
|
||||
|
||||
case nod_parameter:
|
||||
if (dsqlScratch->isPsql())
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-104) <<
|
||||
Arg::Gds(isc_dsql_command_err));
|
||||
}
|
||||
|
||||
{ // scope
|
||||
node = MAKE_node(input->nod_type, e_par_count);
|
||||
node->nod_count = 0;
|
||||
dsql_msg* tempMsg = input->nod_arg[e_par_parameter] ?
|
||||
(dsql_msg*) ((dsql_par*) input->nod_arg[e_par_parameter])->par_message :
|
||||
dsqlScratch->getStatement()->getSendMsg();
|
||||
|
||||
dsql_par* tempPar =
|
||||
MAKE_parameter(tempMsg, true, true, (USHORT)(IPTR) input->nod_arg[e_par_index], NULL);
|
||||
node->nod_arg[e_par_parameter] = (dsql_nod*) tempPar;
|
||||
node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) tempPar->par_index;
|
||||
} // end scope
|
||||
return node;
|
||||
|
||||
// access plan node types
|
||||
|
||||
case nod_plan_item:
|
||||
@ -2498,6 +2465,8 @@ static dsql_nod* explode_fields(dsql_rel* relation)
|
||||
**/
|
||||
static dsql_nod* explode_outputs( DsqlCompilerScratch* dsqlScratch, const dsql_prc* procedure)
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
DEV_BLKCHK(dsqlScratch, dsql_type_req);
|
||||
DEV_BLKCHK(procedure, dsql_type_prc);
|
||||
|
||||
@ -2508,13 +2477,20 @@ static dsql_nod* explode_outputs( DsqlCompilerScratch* dsqlScratch, const dsql_p
|
||||
{
|
||||
DEV_BLKCHK(field, dsql_type_fld);
|
||||
DEV_BLKCHK(*ptr, dsql_type_nod);
|
||||
dsql_nod* p_node = MAKE_node(nod_parameter, e_par_count);
|
||||
*ptr = p_node;
|
||||
|
||||
ParameterNode* paramNode = FB_NEW(*tdbb->getDefaultPool()) ParameterNode(
|
||||
*tdbb->getDefaultPool());
|
||||
|
||||
dsql_nod* p_node = MAKE_node(nod_class_exprnode, 1);
|
||||
p_node->nod_count = 0;
|
||||
dsql_par* parameter = MAKE_parameter(dsqlScratch->getStatement()->getReceiveMsg(),
|
||||
p_node->nod_arg[0] = reinterpret_cast<dsql_nod*>(paramNode);
|
||||
|
||||
*ptr = p_node;
|
||||
dsql_par* parameter = paramNode->dsqlParameter = MAKE_parameter(
|
||||
dsqlScratch->getStatement()->getReceiveMsg(),
|
||||
true, true, 0, NULL);
|
||||
p_node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index;
|
||||
p_node->nod_arg[e_par_parameter] = (dsql_nod*) parameter;
|
||||
paramNode->dsqlParameterIndex = parameter->par_index;
|
||||
|
||||
MAKE_desc_from_field(¶meter->par_desc, field);
|
||||
parameter->par_name = parameter->par_alias = field->fld_name.c_str();
|
||||
parameter->par_rel_name = procedure->prc_name.identifier.c_str();
|
||||
@ -2963,16 +2939,13 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_
|
||||
return PASS1_node_match(map1->map_node, map2->map_node, ignore_map_cast);
|
||||
}
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
case nod_cast:
|
||||
if (node1->nod_arg[0] != node2->nod_arg[0]) {
|
||||
if (node1->nod_arg[0] != node2->nod_arg[0])
|
||||
return false;
|
||||
}
|
||||
|
||||
if (node1->nod_count == 2) {
|
||||
if (node1->nod_count == 2)
|
||||
return PASS1_node_match(node1->nod_arg[1], node2->nod_arg[1], ignore_map_cast);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
case nod_variable:
|
||||
@ -2992,14 +2965,6 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_
|
||||
return true;
|
||||
}
|
||||
|
||||
case nod_parameter:
|
||||
{
|
||||
// Parameters are equal when there index is the same
|
||||
const dsql_par* parameter1 = (dsql_par*) node1->nod_arg[e_par_parameter];
|
||||
const dsql_par* parameter2 = (dsql_par*) node2->nod_arg[e_par_parameter];
|
||||
return (parameter1->par_index == parameter2->par_index);
|
||||
}
|
||||
|
||||
case nod_derived_table:
|
||||
{
|
||||
const dsql_ctx* ctx1 = (dsql_ctx*) node1->nod_arg[e_derived_table_context];
|
||||
@ -3618,7 +3583,7 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const
|
||||
temp->nod_arg[0] = relation_node;
|
||||
|
||||
ComparativeBoolNode* eqlNode = FB_NEW(pool) ComparativeBoolNode(pool,
|
||||
blr_eql, MAKE_node(nod_dbkey, 1), MAKE_node(nod_parameter, e_par_count));
|
||||
blr_eql, MAKE_node(nod_dbkey, 1), MAKE_node(nod_class_exprnode, 1));
|
||||
|
||||
dsql_nod* node = MAKE_node(nod_class_exprnode, 1);
|
||||
node->nod_arg[0] = reinterpret_cast<dsql_nod*>(eqlNode);
|
||||
@ -3630,15 +3595,19 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const
|
||||
dsql_par* parameter = MAKE_parameter(dsqlScratch->getStatement()->getSendMsg(),
|
||||
false, false, 0, NULL);
|
||||
dsqlScratch->getStatement()->setDbKey(parameter);
|
||||
eqlNode->dsqlArg2->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index;
|
||||
eqlNode->dsqlArg2->nod_arg[e_par_parameter] = (dsql_nod*) parameter;
|
||||
|
||||
ParameterNode* paramNode = FB_NEW(pool) ParameterNode(pool);
|
||||
eqlNode->dsqlArg2->nod_arg[0] = reinterpret_cast<dsql_nod*>(paramNode);
|
||||
paramNode->dsqlParameterIndex = parameter->par_index;
|
||||
paramNode->dsqlParameter = parameter;
|
||||
|
||||
parameter->par_desc = source->par_desc;
|
||||
|
||||
// record version will be set only for V4 - for the parent select cursor
|
||||
if (rv_source)
|
||||
{
|
||||
eqlNode = FB_NEW(pool) ComparativeBoolNode(pool,
|
||||
blr_eql, MAKE_node(nod_rec_version, 1), MAKE_node(nod_parameter, e_par_count));
|
||||
blr_eql, MAKE_node(nod_rec_version, 1), MAKE_node(nod_class_exprnode, 1));
|
||||
|
||||
node = MAKE_node(nod_class_exprnode, 1);
|
||||
node->nod_arg[0] = reinterpret_cast<dsql_nod*>(eqlNode);
|
||||
@ -3648,8 +3617,12 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const
|
||||
parameter = MAKE_parameter(dsqlScratch->getStatement()->getSendMsg(),
|
||||
false, false, 0, NULL);
|
||||
dsqlScratch->getStatement()->setRecVersion(parameter);
|
||||
eqlNode->dsqlArg2->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index;
|
||||
eqlNode->dsqlArg2->nod_arg[e_par_parameter] = (dsql_nod*) parameter;
|
||||
|
||||
paramNode = FB_NEW(pool) ParameterNode(pool);
|
||||
eqlNode->dsqlArg2->nod_arg[0] = reinterpret_cast<dsql_nod*>(paramNode);
|
||||
paramNode->dsqlParameterIndex = parameter->par_index;
|
||||
paramNode->dsqlParameter = parameter;
|
||||
|
||||
parameter->par_desc = rv_source->par_desc;
|
||||
|
||||
rse->nod_arg[e_rse_boolean] = PASS1_compose(rse->nod_arg[e_rse_boolean], node, blr_and);
|
||||
@ -4808,7 +4781,6 @@ static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_no
|
||||
case nod_dbkey:
|
||||
case nod_field:
|
||||
case nod_null:
|
||||
case nod_parameter:
|
||||
case nod_variable:
|
||||
return NULL;
|
||||
|
||||
@ -4821,6 +4793,7 @@ static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_no
|
||||
case ExprNode::TYPE_CURRENT_ROLE:
|
||||
case ExprNode::TYPE_CURRENT_USER:
|
||||
case ExprNode::TYPE_INTERNAL_INFO:
|
||||
case ExprNode::TYPE_PARAMETER:
|
||||
return NULL;
|
||||
}
|
||||
break;
|
||||
@ -6349,6 +6322,8 @@ static dsql_rel* pass1_base_table( DsqlCompilerScratch* dsqlScratch, const dsql_
|
||||
**/
|
||||
static dsql_nod* pass1_returning(DsqlCompilerScratch* dsqlScratch, const dsql_nod* input)
|
||||
{
|
||||
thread_db* tdbb = JRD_get_thread_data();
|
||||
|
||||
DEV_BLKCHK(dsqlScratch, dsql_type_req);
|
||||
DEV_BLKCHK(input, dsql_type_nod);
|
||||
|
||||
@ -6419,10 +6394,14 @@ static dsql_nod* pass1_returning(DsqlCompilerScratch* dsqlScratch, const dsql_no
|
||||
MAKE_desc(dsqlScratch, ¶meter->par_desc, *src, NULL);
|
||||
parameter->par_desc.dsc_flags |= DSC_nullable;
|
||||
|
||||
dsql_nod* p_node = MAKE_node(nod_parameter, e_par_count);
|
||||
ParameterNode* paramNode = FB_NEW(*tdbb->getDefaultPool()) ParameterNode(
|
||||
*tdbb->getDefaultPool());
|
||||
paramNode->dsqlParameterIndex = parameter->par_index;
|
||||
paramNode->dsqlParameter = parameter;
|
||||
|
||||
dsql_nod* p_node = MAKE_node(nod_class_exprnode, 1);
|
||||
p_node->nod_count = 0;
|
||||
p_node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index;
|
||||
p_node->nod_arg[e_par_parameter] = (dsql_nod*) parameter;
|
||||
p_node->nod_arg[0] = reinterpret_cast<dsql_nod*>(paramNode);
|
||||
|
||||
dsql_nod* temp = MAKE_node(nod_assign, e_asgn_count);
|
||||
temp->nod_arg[e_asgn_value] = *src;
|
||||
@ -6432,9 +6411,7 @@ static dsql_nod* pass1_returning(DsqlCompilerScratch* dsqlScratch, const dsql_no
|
||||
}
|
||||
|
||||
if (!dsqlScratch->isPsql())
|
||||
{
|
||||
dsqlScratch->getStatement()->setType(DsqlCompiledStatement::TYPE_EXEC_PROCEDURE);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -7097,10 +7074,10 @@ static dsql_nod* pass1_simple_case( DsqlCompilerScratch* dsqlScratch, dsql_nod*
|
||||
{ // scope block
|
||||
DsqlNodStack stack;
|
||||
dsql_nod** ptr = list->nod_arg;
|
||||
|
||||
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ptr += 2)
|
||||
{
|
||||
pass1_put_args_on_stack(dsqlScratch, *ptr, stack);
|
||||
}
|
||||
|
||||
node->nod_arg[e_simple_case_when_operands] = MAKE_list(stack);
|
||||
} // end scope block
|
||||
|
||||
@ -7110,28 +7087,32 @@ static dsql_nod* pass1_simple_case( DsqlCompilerScratch* dsqlScratch, dsql_nod*
|
||||
DsqlNodStack stack;
|
||||
dsql_nod** ptr = list->nod_arg;
|
||||
const dsql_nod* const* const end = ptr + list->nod_count;
|
||||
for (++ptr; ptr < end; ptr += 2) {
|
||||
|
||||
for (++ptr; ptr < end; ptr += 2)
|
||||
pass1_put_args_on_stack(dsqlScratch, *ptr, stack);
|
||||
}
|
||||
|
||||
pass1_put_args_on_stack(dsqlScratch, input->nod_arg[2], stack);
|
||||
node->nod_arg[e_simple_case_results] = MAKE_list(stack);
|
||||
} // end scope block
|
||||
|
||||
// Check if there is a parameter in the case/when operand list
|
||||
bool setParameters = (node->nod_arg[e_simple_case_case_operand]->nod_type == nod_parameter);
|
||||
bool setParameters = ExprNode::is<ParameterNode>(node->nod_arg[e_simple_case_case_operand]);
|
||||
|
||||
if (!setParameters)
|
||||
{
|
||||
list = node->nod_arg[e_simple_case_when_operands];
|
||||
dsql_nod** ptr = list->nod_arg;
|
||||
|
||||
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ++ptr)
|
||||
{
|
||||
if ((*ptr)->nod_type == nod_parameter)
|
||||
if (ExprNode::is<ParameterNode>(*ptr))
|
||||
{
|
||||
setParameters = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// build list for making describe information from
|
||||
// case_operand and when_operands this is used for
|
||||
// setting parameter describers if used in this case.
|
||||
@ -7144,10 +7125,10 @@ static dsql_nod* pass1_simple_case( DsqlCompilerScratch* dsqlScratch, dsql_nod*
|
||||
int i = 0;
|
||||
node1->nod_arg[i++] = node->nod_arg[e_simple_case_case_operand];
|
||||
dsql_nod** ptr = list->nod_arg;
|
||||
|
||||
for (const dsql_nod* const* const end = ptr + list->nod_count; ptr < end; ++ptr, ++i)
|
||||
{
|
||||
node1->nod_arg[i] = *ptr;
|
||||
}
|
||||
|
||||
MAKE_desc_from_list(dsqlScratch, &node1->nod_desc, node1, NULL, "CASE");
|
||||
// Set parameter describe information
|
||||
PASS1_set_parameter_type(dsqlScratch, node->nod_arg[e_simple_case_case_operand], node1, false);
|
||||
@ -7156,10 +7137,9 @@ static dsql_nod* pass1_simple_case( DsqlCompilerScratch* dsqlScratch, dsql_nod*
|
||||
{ // scope block
|
||||
dsql_nod* simple_when = node->nod_arg[e_simple_case_when_operands];
|
||||
dsql_nod** ptr = simple_when->nod_arg;
|
||||
|
||||
for (const dsql_nod* const* const end = ptr + simple_when->nod_count; ptr < end; ptr++)
|
||||
{
|
||||
PASS1_set_parameter_type(dsqlScratch, *ptr, node1, false);
|
||||
}
|
||||
} // end scope block
|
||||
|
||||
// Clean up temporary used node
|
||||
@ -7171,10 +7151,9 @@ static dsql_nod* pass1_simple_case( DsqlCompilerScratch* dsqlScratch, dsql_nod*
|
||||
// Set parameter describe information for evt. results parameters
|
||||
dsql_nod* simple_res = node->nod_arg[e_simple_case_results];
|
||||
dsql_nod** ptr = simple_res->nod_arg;
|
||||
|
||||
for (const dsql_nod* const* const end = ptr + simple_res->nod_count; ptr < end; ptr++)
|
||||
{
|
||||
PASS1_set_parameter_type(dsqlScratch, *ptr, node, false);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
@ -8529,140 +8508,18 @@ bool PASS1_set_parameter_type(DsqlCompilerScratch* dsqlScratch, dsql_nod* in_nod
|
||||
case nod_class_exprnode:
|
||||
{
|
||||
ValueExprNode* exprNode = reinterpret_cast<ValueExprNode*>(in_node->nod_arg[0]);
|
||||
return exprNode->setParameterType(dsqlScratch, node, force_varchar);
|
||||
return exprNode->setParameterType(dsqlScratch, in_node, node, force_varchar);
|
||||
}
|
||||
|
||||
case nod_parameter:
|
||||
{
|
||||
if (!node)
|
||||
in_node->nod_desc.makeNullString();
|
||||
else
|
||||
{
|
||||
MAKE_desc(dsqlScratch, &in_node->nod_desc, node, NULL);
|
||||
|
||||
if (tdbb->getCharSet() != CS_NONE && tdbb->getCharSet() != CS_BINARY)
|
||||
{
|
||||
const USHORT fromCharSet = in_node->nod_desc.getCharSet();
|
||||
const USHORT toCharSet = (fromCharSet == CS_NONE || fromCharSet == CS_BINARY) ?
|
||||
fromCharSet : tdbb->getCharSet();
|
||||
|
||||
if (in_node->nod_desc.dsc_dtype <= dtype_any_text)
|
||||
{
|
||||
int diff = 0;
|
||||
switch (in_node->nod_desc.dsc_dtype)
|
||||
{
|
||||
case dtype_varying:
|
||||
diff = sizeof(USHORT);
|
||||
break;
|
||||
case dtype_cstring:
|
||||
diff = 1;
|
||||
break;
|
||||
}
|
||||
in_node->nod_desc.dsc_length -= diff;
|
||||
|
||||
if (toCharSet != fromCharSet)
|
||||
{
|
||||
const USHORT fromCharSetBPC = METD_get_charset_bpc(
|
||||
dsqlScratch->getTransaction(), fromCharSet);
|
||||
const USHORT toCharSetBPC = METD_get_charset_bpc(
|
||||
dsqlScratch->getTransaction(), toCharSet);
|
||||
|
||||
in_node->nod_desc.setTextType(INTL_CS_COLL_TO_TTYPE(toCharSet,
|
||||
(fromCharSet == toCharSet ? INTL_GET_COLLATE(&in_node->nod_desc) : 0)));
|
||||
|
||||
in_node->nod_desc.dsc_length =
|
||||
UTLD_char_length_to_byte_length(in_node->nod_desc.dsc_length / fromCharSetBPC, toCharSetBPC);
|
||||
}
|
||||
|
||||
in_node->nod_desc.dsc_length += diff;
|
||||
}
|
||||
else if (in_node->nod_desc.dsc_dtype == dtype_blob &&
|
||||
in_node->nod_desc.dsc_sub_type == isc_blob_text &&
|
||||
fromCharSet != CS_NONE && fromCharSet != CS_BINARY)
|
||||
{
|
||||
in_node->nod_desc.setTextType(toCharSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dsql_par* parameter = (dsql_par*) in_node->nod_arg[e_par_parameter];
|
||||
|
||||
if (!parameter)
|
||||
{
|
||||
parameter = MAKE_parameter(dsqlScratch->getStatement()->getSendMsg(), true, true,
|
||||
(USHORT)(IPTR) in_node->nod_arg[e_par_index], NULL);
|
||||
in_node->nod_arg[e_par_parameter] = (dsql_nod*) parameter;
|
||||
in_node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index;
|
||||
}
|
||||
|
||||
// In case of RETURNING in MERGE and UPDATE OR INSERT, a single parameter is used in
|
||||
// more than one place. So we save it to use below.
|
||||
dsc oldDesc = parameter->par_desc;
|
||||
bool hasOldDesc = parameter->par_node != NULL;
|
||||
|
||||
parameter->par_desc = in_node->nod_desc;
|
||||
parameter->par_node = in_node;
|
||||
|
||||
// Parameters should receive precisely the data that the user
|
||||
// passes in. Therefore for text strings lets use varying
|
||||
// strings to insure that we don't add trailing blanks.
|
||||
|
||||
// However, there are situations this leads to problems - so
|
||||
// we use the force_varchar parameter to prevent this
|
||||
// datatype assumption from occuring.
|
||||
|
||||
if (force_varchar)
|
||||
{
|
||||
if (parameter->par_desc.dsc_dtype == dtype_text)
|
||||
{
|
||||
parameter->par_desc.dsc_dtype = dtype_varying;
|
||||
// The error msgs is inaccurate, but causing dsc_length
|
||||
// to be outsise range can be worse.
|
||||
if (parameter->par_desc.dsc_length > MAX_COLUMN_SIZE - sizeof(USHORT))
|
||||
{
|
||||
ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) <<
|
||||
//Arg::Gds(isc_dsql_datatype_err)
|
||||
Arg::Gds(isc_imp_exc));
|
||||
//Arg::Gds(isc_field_name) << Arg::Str(parameter->par_name)
|
||||
}
|
||||
|
||||
parameter->par_desc.dsc_length += sizeof(USHORT);
|
||||
}
|
||||
else if (parameter->par_desc.dsc_dtype > dtype_any_text)
|
||||
{
|
||||
const USHORT toCharSetBPC = METD_get_charset_bpc(
|
||||
dsqlScratch->getTransaction(), tdbb->getCharSet());
|
||||
|
||||
// The LIKE & similar parameters must be varchar type
|
||||
// strings - so force this parameter to be varchar
|
||||
// and take a guess at a good length for it.
|
||||
parameter->par_desc.dsc_dtype = dtype_varying;
|
||||
parameter->par_desc.dsc_length = LIKE_PARAM_LEN * toCharSetBPC +
|
||||
sizeof(USHORT);
|
||||
parameter->par_desc.dsc_sub_type = 0;
|
||||
parameter->par_desc.dsc_scale = 0;
|
||||
parameter->par_desc.dsc_ttype() = ttype_dynamic;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOldDesc)
|
||||
{
|
||||
dsc thisDesc = parameter->par_desc;
|
||||
const dsc* args[] = {&oldDesc, &thisDesc};
|
||||
DSqlDataTypeUtil(dsqlScratch).makeFromList(¶meter->par_desc,
|
||||
parameter->par_name.c_str(), 2, args);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case nod_cast:
|
||||
{
|
||||
dsql_nod* par_node = in_node->nod_arg[e_cast_source];
|
||||
dsql_fld* field = (dsql_fld*) in_node->nod_arg[e_cast_target];
|
||||
if (par_node->nod_type == nod_parameter)
|
||||
ParameterNode* paramNode;
|
||||
|
||||
if ((paramNode = ExprNode::as<ParameterNode>(par_node)))
|
||||
{
|
||||
dsql_par* parameter = (dsql_par*) par_node->nod_arg[e_par_parameter];
|
||||
dsql_par* parameter = paramNode->dsqlParameter;
|
||||
if (parameter)
|
||||
{
|
||||
parameter->par_desc = par_node->nod_desc;
|
||||
@ -8786,20 +8643,21 @@ static void set_parameter_name( dsql_nod* par_node, const dsql_nod* fld_node, co
|
||||
set_parameter_name(**i, fld_node, relation);
|
||||
}
|
||||
break;
|
||||
|
||||
case ExprNode::TYPE_PARAMETER:
|
||||
{
|
||||
ParameterNode* paramNode = exprNode->as<ParameterNode>();
|
||||
dsql_par* parameter = paramNode->dsqlParameter;
|
||||
const dsql_fld* field = (dsql_fld*) fld_node->nod_arg[e_fld_field];
|
||||
DEV_BLKCHK(field, dsql_type_fld);
|
||||
parameter->par_name = field->fld_name.c_str();
|
||||
parameter->par_rel_name = relation->rel_name.c_str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
||||
case nod_parameter:
|
||||
{
|
||||
dsql_par* parameter = (dsql_par*) par_node->nod_arg[e_par_parameter];
|
||||
const dsql_fld* field = (dsql_fld*) fld_node->nod_arg[e_fld_field];
|
||||
DEV_BLKCHK(field, dsql_type_fld);
|
||||
parameter->par_name = field->fld_name.c_str();
|
||||
parameter->par_rel_name = relation->rel_name.c_str();
|
||||
return;
|
||||
}
|
||||
|
||||
case nod_substr:
|
||||
case nod_trim:
|
||||
case nod_upcase:
|
||||
@ -9054,9 +8912,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
|
||||
case nod_foreign:
|
||||
verb = "foreign key";
|
||||
break;
|
||||
case nod_gen_id:
|
||||
verb = "gen_id";
|
||||
break;
|
||||
case nod_get_segment:
|
||||
verb = "get segment";
|
||||
break;
|
||||
@ -9172,9 +9027,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
|
||||
verb = "searched_case";
|
||||
break;
|
||||
|
||||
case nod_gen_id2:
|
||||
verb = "gen_id2";
|
||||
break;
|
||||
case nod_limit:
|
||||
verb = "limit";
|
||||
break;
|
||||
@ -9585,17 +9437,6 @@ void DSQL_pretty(const dsql_nod* node, int column)
|
||||
trace_line("%s\"\n", string->str_data);
|
||||
return;
|
||||
|
||||
case nod_parameter:
|
||||
if (node->nod_column) {
|
||||
trace_line("%sparameter: %d\n", buffer, (USHORT)(IPTR)node->nod_arg[e_par_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const dsql_par* param = (dsql_par*) node->nod_arg[e_par_parameter];
|
||||
trace_line("%sparameter: %d\n", buffer, param->par_index);
|
||||
}
|
||||
return;
|
||||
|
||||
case nod_cursor_open:
|
||||
verb = "cursor_open";
|
||||
break;
|
||||
|
@ -341,10 +341,6 @@ bool OPT_expression_equal2(thread_db* tdbb, CompilerScratch* csb,
|
||||
return true;
|
||||
}
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
return node1->nod_arg[e_gen_id] == node2->nod_arg[e_gen_id];
|
||||
|
||||
case nod_upcase:
|
||||
case nod_lowcase:
|
||||
return OPT_expression_equal2(tdbb, csb, node1->nod_arg[0], node2->nod_arg[0], stream);
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "../jrd/sdl.h"
|
||||
#include "../jrd/intl.h"
|
||||
#include "../jrd/cch.h"
|
||||
#include "../dsql/ExprNodes.h"
|
||||
#include "../jrd/gdsassert.h"
|
||||
#include "../jrd/blb_proto.h"
|
||||
#include "../jrd/blf_proto.h"
|
||||
@ -75,7 +76,6 @@
|
||||
|
||||
using namespace Jrd;
|
||||
using namespace Firebird;
|
||||
using Firebird::UCharBuffer;
|
||||
|
||||
typedef Ods::blob_page blob_page;
|
||||
|
||||
@ -987,9 +987,15 @@ void BLB_move(thread_db* tdbb, dsc* from_desc, dsc* to_desc, const jrd_nod* fiel
|
||||
simpleMove =
|
||||
tdbb->getRequest()->req_rpb[(IPTR)field->nod_arg[e_fld_stream]].rpb_relation == NULL;
|
||||
break;
|
||||
case nod_argument:
|
||||
|
||||
case nod_variable:
|
||||
break;
|
||||
|
||||
case nod_class_exprnode_jrd:
|
||||
if (ExprNode::is<ParameterNode>(field))
|
||||
break;
|
||||
// fall into
|
||||
|
||||
default:
|
||||
BUGCHECK(199); // msg 199 expected field node
|
||||
}
|
||||
|
134
src/jrd/cmp.cpp
134
src/jrd/cmp.cpp
@ -169,7 +169,6 @@ static void pass1_modify(thread_db*, CompilerScratch*, jrd_nod*);
|
||||
static bool pass1_store(thread_db*, CompilerScratch*, jrd_nod*);
|
||||
static RelationSourceNode* pass1_update(thread_db*, CompilerScratch*, jrd_rel*, const trig_vec*, USHORT, USHORT,
|
||||
SecurityClass::flags_t, jrd_rel*, USHORT);
|
||||
static jrd_nod* pass2_validation(thread_db*, CompilerScratch*, const Item&);
|
||||
static void post_trigger_access(CompilerScratch*, jrd_rel*, ExternalAccess::exa_act, jrd_rel*);
|
||||
|
||||
#ifdef CMP_DEBUG
|
||||
@ -209,7 +208,7 @@ jrd_nod* CMP_clone_node_opt(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node
|
||||
DEV_BLKCHK(csb, type_csb);
|
||||
DEV_BLKCHK(node, type_nod);
|
||||
|
||||
if (node->nod_type == nod_argument)
|
||||
if (ExprNode::is<ParameterNode>(node))
|
||||
return node;
|
||||
|
||||
jrd_nod* clone = NodeCopier::copy(tdbb, csb, node, NULL);
|
||||
@ -486,7 +485,6 @@ void CMP_get_desc(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node, DSC* des
|
||||
case nod_prot_mask:
|
||||
case nod_null:
|
||||
case nod_count:
|
||||
case nod_gen_id:
|
||||
case nod_lock_state:
|
||||
desc->dsc_dtype = dtype_long;
|
||||
desc->dsc_length = sizeof(SLONG);
|
||||
@ -566,14 +564,6 @@ void CMP_get_desc(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node, DSC* des
|
||||
desc->dsc_flags = 0;
|
||||
return;
|
||||
|
||||
case nod_gen_id2:
|
||||
desc->dsc_dtype = dtype_int64;
|
||||
desc->dsc_length = sizeof(SINT64);
|
||||
desc->dsc_scale = 0;
|
||||
desc->dsc_sub_type = 0;
|
||||
desc->dsc_flags = 0;
|
||||
return;
|
||||
|
||||
case nod_class_exprnode_jrd:
|
||||
{
|
||||
ValueExprNode* exprNode = reinterpret_cast<ValueExprNode*>(node->nod_arg[0]);
|
||||
@ -686,14 +676,6 @@ void CMP_get_desc(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node, DSC* des
|
||||
return;
|
||||
}
|
||||
|
||||
case nod_argument:
|
||||
{
|
||||
const jrd_nod* message = node->nod_arg[e_arg_message];
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
*desc = format->fmt_desc[(IPTR) node->nod_arg[e_arg_number]];
|
||||
return;
|
||||
}
|
||||
|
||||
case nod_substr:
|
||||
{
|
||||
DSC desc0, desc1, desc2, desc3;
|
||||
@ -1253,40 +1235,6 @@ jrd_nod* NodeCopier::copy(thread_db* tdbb, jrd_nod* input)
|
||||
}
|
||||
return node;
|
||||
|
||||
case nod_argument:
|
||||
if (remapArgument())
|
||||
return input;
|
||||
node = PAR_make_node(tdbb, e_arg_length);
|
||||
node->nod_count = input->nod_count;
|
||||
node->nod_flags = input->nod_flags;
|
||||
node->nod_type = input->nod_type;
|
||||
node->nod_arg[e_arg_number] = input->nod_arg[e_arg_number];
|
||||
// dimitr: IMPORTANT!!!
|
||||
// nod_message copying must be done in the only place
|
||||
// (the nod_procedure code below). Hence we don't call
|
||||
// copy() here to keep argument->nod_arg[e_arg_message]
|
||||
// and procedure->nod_arg[e_prc_in_msg] in sync. The
|
||||
// message is passed to copy() as a parameter. If the
|
||||
// passed message is NULL, it means nod_argument is
|
||||
// cloned outside nod_procedure (e.g. in the optimizer)
|
||||
// and we must keep the input message.
|
||||
// ASF: We should only use "message" if its number matches the number
|
||||
// in nod_argument. If it don't, it may be an input parameter cloned
|
||||
// in RseBoolNode::convertNeqAllToNotAny - see CORE-3094.
|
||||
|
||||
if (message &&
|
||||
(IPTR) message->nod_arg[e_msg_number] ==
|
||||
(IPTR) input->nod_arg[e_arg_message]->nod_arg[e_msg_number])
|
||||
{
|
||||
node->nod_arg[e_arg_message] = message;
|
||||
}
|
||||
else
|
||||
node->nod_arg[e_arg_message] = input->nod_arg[e_arg_message];
|
||||
|
||||
node->nod_arg[e_arg_flag] = copy(tdbb, input->nod_arg[e_arg_flag]);
|
||||
node->nod_arg[e_arg_indicator] = copy(tdbb, input->nod_arg[e_arg_indicator]);
|
||||
return node;
|
||||
|
||||
case nod_assignment:
|
||||
args = e_asgn_length;
|
||||
break;
|
||||
@ -1385,15 +1333,6 @@ jrd_nod* NodeCopier::copy(thread_db* tdbb, jrd_nod* input)
|
||||
return node;
|
||||
}
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2: // 20001013 PJPG
|
||||
node = PAR_make_node(tdbb, e_gen_length);
|
||||
node->nod_count = input->nod_count;
|
||||
node->nod_type = input->nod_type;
|
||||
node->nod_arg[e_gen_value] = copy(tdbb, input->nod_arg[e_gen_value]);
|
||||
node->nod_arg[e_gen_id] = input->nod_arg[e_gen_id];
|
||||
return (node);
|
||||
|
||||
case nod_cast:
|
||||
node = PAR_make_node(tdbb, e_cast_length);
|
||||
node->nod_count = input->nod_count;
|
||||
@ -1671,22 +1610,23 @@ static jrd_nod* make_defaults(thread_db* tdbb, CompilerScratch* csb, USHORT stre
|
||||
{
|
||||
// Make a gen_id(<generator name>, 1) expression.
|
||||
|
||||
jrd_nod* genNode = PAR_make_node(tdbb, e_gen_length);
|
||||
genNode->nod_type = nod_gen_id;
|
||||
genNode->nod_count = 1;
|
||||
|
||||
const SLONG tmp = MET_lookup_generator(tdbb, (*ptr1)->fld_generator_name.c_str());
|
||||
genNode->nod_arg[e_gen_id] = (jrd_nod*)(IPTR) tmp;
|
||||
GenIdNode* genNode = FB_NEW(csb->csb_pool) GenIdNode(csb->csb_pool,
|
||||
(csb->csb_g_flags & csb_blr_version4), (*ptr1)->fld_generator_name);
|
||||
genNode->id = MET_lookup_generator(tdbb, (*ptr1)->fld_generator_name.c_str());
|
||||
|
||||
const int count = lit_delta + (sizeof(SLONG) + sizeof(jrd_nod*) - 1) / sizeof(jrd_nod*);
|
||||
jrd_nod* literalNode = genNode->nod_arg[e_gen_value] = PAR_make_node(tdbb, count);
|
||||
jrd_nod* literalNode = genNode->arg = PAR_make_node(tdbb, count);
|
||||
literalNode->nod_type = nod_literal;
|
||||
literalNode->nod_count = 0;
|
||||
Literal* literal = (Literal*) literalNode;
|
||||
literal->lit_desc.makeLong(0, (SLONG*) literal->lit_data);
|
||||
*(SLONG*) literal->lit_data = 1;
|
||||
|
||||
node->nod_arg[e_asgn_from] = genNode;
|
||||
jrd_nod* genNod = PAR_make_node(tdbb, 1);
|
||||
genNod->nod_type = nod_class_exprnode_jrd;
|
||||
genNod->nod_count = 0;
|
||||
genNod->nod_arg[0] = reinterpret_cast<jrd_nod*>(genNode);
|
||||
node->nod_arg[e_asgn_from] = genNod;
|
||||
}
|
||||
else //if (value)
|
||||
{
|
||||
@ -1919,9 +1859,6 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
}
|
||||
break;
|
||||
|
||||
case nod_argument:
|
||||
break;
|
||||
|
||||
case nod_cast:
|
||||
{
|
||||
dsc desc;
|
||||
@ -2249,11 +2186,6 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
reinterpret_cast<RecordSourceNode*>(node->nod_arg[0])->pass1(tdbb, csb, view);
|
||||
break;
|
||||
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
node->nod_arg[e_gen_value] = CMP_pass1(tdbb, csb, node->nod_arg[e_gen_value]);
|
||||
return node;
|
||||
|
||||
case nod_rec_version:
|
||||
case nod_dbkey:
|
||||
{
|
||||
@ -2432,6 +2364,7 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
if (node->nod_type == nod_assignment)
|
||||
{
|
||||
sub = node->nod_arg[e_asgn_to];
|
||||
|
||||
switch (sub->nod_type)
|
||||
{
|
||||
case nod_field:
|
||||
@ -2451,11 +2384,16 @@ jrd_nod* CMP_pass1(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node)
|
||||
ERR_post(Arg::Gds(isc_read_only_field));
|
||||
}
|
||||
break;
|
||||
case nod_argument:
|
||||
|
||||
case nod_variable:
|
||||
case nod_null:
|
||||
// Nothing to do here
|
||||
break;
|
||||
break; // Nothing to do here
|
||||
|
||||
case nod_class_exprnode_jrd:
|
||||
if (ExprNode::is<ParameterNode>(sub))
|
||||
break; // Nothing to do here
|
||||
// fall into
|
||||
|
||||
default:
|
||||
ERR_post(Arg::Gds(isc_read_only_field));
|
||||
}
|
||||
@ -3001,22 +2939,12 @@ static RelationSourceNode* pass1_update(thread_db* tdbb, CompilerScratch* csb, j
|
||||
}
|
||||
|
||||
|
||||
static jrd_nod* pass2_validation(thread_db* tdbb, CompilerScratch* csb, const Item& item)
|
||||
// Copy items' information into appropriate node.
|
||||
ItemInfo* CMP_pass2_validation(thread_db* tdbb, CompilerScratch* csb, const Item& item)
|
||||
{
|
||||
/**************************************
|
||||
*
|
||||
* p a s s 2 _ v a l i d a t i o n
|
||||
*
|
||||
**************************************
|
||||
*
|
||||
* Functional description
|
||||
* Copy items' information into appropriate node
|
||||
*
|
||||
**************************************/
|
||||
ItemInfo itemInfo;
|
||||
return csb->csb_map_item_info.get(item, itemInfo) ?
|
||||
reinterpret_cast<jrd_nod*>(FB_NEW(*tdbb->getDefaultPool())
|
||||
ItemInfo(*tdbb->getDefaultPool(), itemInfo)) : 0;
|
||||
FB_NEW(*tdbb->getDefaultPool()) ItemInfo(*tdbb->getDefaultPool(), itemInfo) : NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -3100,20 +3028,13 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
return node;
|
||||
|
||||
case nod_variable:
|
||||
node->nod_arg[e_var_info] =
|
||||
pass2_validation(tdbb, csb, Item(nod_variable, (IPTR) node->nod_arg[e_var_id]));
|
||||
node->nod_arg[e_var_info] = reinterpret_cast<jrd_nod*>(CMP_pass2_validation(tdbb,
|
||||
csb, Item(Item::TYPE_VARIABLE, (IPTR) node->nod_arg[e_var_id])));
|
||||
break;
|
||||
|
||||
case nod_init_variable:
|
||||
node->nod_arg[e_init_var_info] =
|
||||
pass2_validation(tdbb, csb, Item(nod_variable, (IPTR) node->nod_arg[e_init_var_id]));
|
||||
break;
|
||||
|
||||
case nod_argument:
|
||||
node->nod_arg[e_arg_info] =
|
||||
pass2_validation(tdbb, csb, Item(nod_argument,
|
||||
(IPTR) node->nod_arg[e_arg_message]->nod_arg[e_msg_number],
|
||||
(IPTR) node->nod_arg[e_arg_number]));
|
||||
node->nod_arg[e_init_var_info] = reinterpret_cast<jrd_nod*>(CMP_pass2_validation(tdbb,
|
||||
csb, Item(Item::TYPE_VARIABLE, (IPTR) node->nod_arg[e_init_var_id])));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -3279,7 +3200,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
break;
|
||||
}
|
||||
|
||||
case nod_argument:
|
||||
case nod_variable:
|
||||
node->nod_impure = CMP_impure(csb, (node->nod_flags & nod_value) ?
|
||||
sizeof(impure_value_ex) : sizeof(dsc));
|
||||
@ -3291,8 +3211,6 @@ jrd_nod* CMP_pass2(thread_db* tdbb, CompilerScratch* csb, jrd_nod* const node, j
|
||||
case nod_substr:
|
||||
case nod_trim:
|
||||
case nod_null:
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
case nod_upcase:
|
||||
case nod_lowcase:
|
||||
case nod_prot_mask:
|
||||
|
@ -47,6 +47,8 @@ Jrd::jrd_nod* CMP_pass1(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::jr
|
||||
Jrd::jrd_nod* CMP_pass2(Jrd::thread_db* tdbb, Jrd::CompilerScratch* csb, Jrd::jrd_nod* const node,
|
||||
Jrd::jrd_nod* parent);
|
||||
|
||||
Jrd::ItemInfo* CMP_pass2_validation(Jrd::thread_db*, Jrd::CompilerScratch*, const Jrd::Item&);
|
||||
|
||||
void CMP_post_access(Jrd::thread_db*, Jrd::CompilerScratch*, const Firebird::MetaName&, SLONG,
|
||||
Jrd::SecurityClass::flags_t, SLONG type_name, const Firebird::MetaName&,
|
||||
const Firebird::MetaName&);
|
||||
|
109
src/jrd/evl.cpp
109
src/jrd/evl.cpp
@ -146,10 +146,6 @@ dsc* EVL_assign_to(thread_db* tdbb, const jrd_nod* node)
|
||||
* destination node of an assignment.
|
||||
*
|
||||
**************************************/
|
||||
const dsc* desc;
|
||||
const Format* format;
|
||||
const jrd_nod* message;
|
||||
Record* record;
|
||||
|
||||
SET_TDBB(tdbb);
|
||||
|
||||
@ -161,33 +157,43 @@ dsc* EVL_assign_to(thread_db* tdbb, const jrd_nod* node)
|
||||
// The only nodes that can be assigned to are: argument, field and variable.
|
||||
|
||||
int arg_number;
|
||||
const dsc* desc;
|
||||
const Format* format;
|
||||
const jrd_nod* message;
|
||||
Record* record;
|
||||
const ParameterNode* paramNode;
|
||||
|
||||
switch (node->nod_type)
|
||||
if ((paramNode = ExprNode::as<ParameterNode>(node)))
|
||||
{
|
||||
case nod_argument:
|
||||
message = node->nod_arg[e_arg_message];
|
||||
message = paramNode->message;
|
||||
format = (Format*) message->nod_arg[e_msg_format];
|
||||
arg_number = (int) (IPTR) node->nod_arg[e_arg_number];
|
||||
arg_number = paramNode->argNumber;
|
||||
desc = &format->fmt_desc[arg_number];
|
||||
|
||||
impure->vlu_desc.dsc_address = request->getImpure<UCHAR>(
|
||||
message->nod_impure + (IPTR) desc->dsc_address);
|
||||
impure->vlu_desc.dsc_dtype = desc->dsc_dtype;
|
||||
impure->vlu_desc.dsc_length = desc->dsc_length;
|
||||
impure->vlu_desc.dsc_scale = desc->dsc_scale;
|
||||
impure->vlu_desc.dsc_sub_type = desc->dsc_sub_type;
|
||||
|
||||
if (DTYPE_IS_TEXT(desc->dsc_dtype) &&
|
||||
((INTL_TTYPE(desc) == ttype_dynamic) || (INTL_GET_CHARSET(desc) == CS_dynamic)))
|
||||
{
|
||||
/* Value is a text value, we're assigning it back to the user
|
||||
process, user process has not specified a subtype, user
|
||||
process specified dynamic translation and the dsc isn't from
|
||||
a 3.3 type request (blr_cstring2 instead of blr_cstring) so
|
||||
convert the charset to the declared charset of the process. */
|
||||
// Value is a text value, we're assigning it back to the user
|
||||
// process, user process has not specified a subtype, user
|
||||
// process specified dynamic translation and the dsc isn't from
|
||||
// a 3.3 type request (blr_cstring2 instead of blr_cstring) so
|
||||
// convert the charset to the declared charset of the process.
|
||||
|
||||
impure->vlu_desc.setTextType(tdbb->getCharSet());
|
||||
}
|
||||
return &impure->vlu_desc;
|
||||
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
switch (node->nod_type)
|
||||
{
|
||||
case nod_field:
|
||||
record = request->req_rpb[(int) (IPTR) node->nod_arg[e_fld_stream]].rpb_record;
|
||||
if (!EVL_field(0, record, (USHORT)(IPTR) node->nod_arg[e_fld_id], &impure->vlu_desc))
|
||||
@ -382,51 +388,6 @@ dsc* EVL_expr(thread_db* tdbb, const jrd_nod* node)
|
||||
return desc;
|
||||
}
|
||||
|
||||
case nod_argument:
|
||||
{
|
||||
const dsc* desc;
|
||||
|
||||
if (node->nod_arg[e_arg_flag])
|
||||
{
|
||||
desc = EVL_expr(tdbb, node->nod_arg[e_arg_flag]);
|
||||
if (MOV_get_long(desc, 0)) {
|
||||
request->req_flags |= req_null;
|
||||
}
|
||||
}
|
||||
const jrd_nod* message = node->nod_arg[e_arg_message];
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
desc = &format->fmt_desc[(int)(IPTR) node->nod_arg[e_arg_number]];
|
||||
|
||||
impure->vlu_desc.dsc_address = request->getImpure<UCHAR>(
|
||||
message->nod_impure + (IPTR) desc->dsc_address);
|
||||
impure->vlu_desc.dsc_dtype = desc->dsc_dtype;
|
||||
impure->vlu_desc.dsc_length = desc->dsc_length;
|
||||
impure->vlu_desc.dsc_scale = desc->dsc_scale;
|
||||
impure->vlu_desc.dsc_sub_type = desc->dsc_sub_type;
|
||||
|
||||
if (impure->vlu_desc.dsc_dtype == dtype_text)
|
||||
INTL_adjust_text_descriptor(tdbb, &impure->vlu_desc);
|
||||
|
||||
USHORT* impure_flags = request->getImpure<USHORT>(
|
||||
(IPTR) message->nod_arg[e_msg_impure_flags] +
|
||||
(sizeof(USHORT) * (IPTR) node->nod_arg[e_arg_number]));
|
||||
|
||||
if (!(*impure_flags & VLU_checked))
|
||||
{
|
||||
if (node->nod_arg[e_arg_info])
|
||||
{
|
||||
EVL_validate(tdbb,
|
||||
Item(nod_argument, (IPTR) node->nod_arg[e_arg_message]->nod_arg[e_msg_number],
|
||||
(IPTR) node->nod_arg[e_arg_number]),
|
||||
reinterpret_cast<const ItemInfo*>(node->nod_arg[e_arg_info]),
|
||||
&impure->vlu_desc, request->req_flags & req_null);
|
||||
}
|
||||
*impure_flags |= VLU_checked;
|
||||
}
|
||||
|
||||
return &impure->vlu_desc;
|
||||
}
|
||||
|
||||
case nod_dbkey:
|
||||
return dbkey(tdbb, node, impure);
|
||||
|
||||
@ -557,7 +518,7 @@ dsc* EVL_expr(thread_db* tdbb, const jrd_nod* node)
|
||||
{
|
||||
if (node->nod_arg[e_var_info])
|
||||
{
|
||||
EVL_validate(tdbb, Item(nod_variable, (IPTR) node->nod_arg[e_var_id]),
|
||||
EVL_validate(tdbb, Item(Item::TYPE_VARIABLE, (IPTR) node->nod_arg[e_var_id]),
|
||||
reinterpret_cast<const ItemInfo*>(node->nod_arg[e_var_info]),
|
||||
&impure->vlu_desc, impure->vlu_desc.dsc_flags & DSC_null);
|
||||
}
|
||||
@ -612,22 +573,6 @@ dsc* EVL_expr(thread_db* tdbb, const jrd_nod* node)
|
||||
|
||||
switch (node->nod_type)
|
||||
{
|
||||
case nod_gen_id: // return a 32-bit generator value
|
||||
{
|
||||
SLONG temp = (SLONG) DPM_gen_id(tdbb, (SLONG)(IPTR) node->nod_arg[e_gen_id],
|
||||
false, MOV_get_int64(values[0], 0));
|
||||
impure->make_long(temp);
|
||||
}
|
||||
return &impure->vlu_desc;
|
||||
|
||||
case nod_gen_id2:
|
||||
{
|
||||
SINT64 temp = DPM_gen_id(tdbb, (IPTR) node->nod_arg[e_gen_id],
|
||||
false, MOV_get_int64(values[0], 0));
|
||||
impure->make_int64(temp);
|
||||
}
|
||||
return &impure->vlu_desc;
|
||||
|
||||
case nod_substr:
|
||||
return substring(tdbb, impure, values[0], values[1], values[2]);
|
||||
|
||||
@ -882,9 +827,7 @@ void EVL_validate(thread_db* tdbb, const Item& item, const ItemInfo* itemInfo, d
|
||||
fieldInfo.validation)
|
||||
{
|
||||
if (desc && null)
|
||||
{
|
||||
desc->dsc_flags |= DSC_null;
|
||||
}
|
||||
|
||||
const bool desc_is_null = !desc || (desc->dsc_flags & DSC_null);
|
||||
|
||||
@ -916,7 +859,7 @@ void EVL_validate(thread_db* tdbb, const Item& item, const ItemInfo* itemInfo, d
|
||||
ISC_STATUS status = isc_not_valid_for_var;
|
||||
const char* arg;
|
||||
|
||||
if (item.type == nod_cast)
|
||||
if (item.type == Item::TYPE_CAST)
|
||||
{
|
||||
status = isc_not_valid_for;
|
||||
arg = "CAST";
|
||||
@ -929,7 +872,7 @@ void EVL_validate(thread_db* tdbb, const Item& item, const ItemInfo* itemInfo, d
|
||||
|
||||
status = isc_not_valid_for;
|
||||
|
||||
if (item.type == nod_variable)
|
||||
if (item.type == Item::TYPE_VARIABLE)
|
||||
{
|
||||
const jrd_prc* procedure = request->getStatement()->procedure;
|
||||
|
||||
@ -946,9 +889,9 @@ void EVL_validate(thread_db* tdbb, const Item& item, const ItemInfo* itemInfo, d
|
||||
else
|
||||
s.printf("variable number %d", index);
|
||||
}
|
||||
else if (item.type == nod_argument && item.subType == 0)
|
||||
else if (item.type == Item::TYPE_PARAMETER && item.subType == 0)
|
||||
s.printf("input parameter number %d", (index - 1) / 2 + 1);
|
||||
else if (item.type == nod_argument && item.subType == 1)
|
||||
else if (item.type == Item::TYPE_PARAMETER && item.subType == 1)
|
||||
s.printf("output parameter number %d", index);
|
||||
|
||||
if (s.isEmpty())
|
||||
@ -1020,7 +963,7 @@ static dsc* cast(thread_db* tdbb, dsc* value, const jrd_nod* node, impure_value*
|
||||
impure->vlu_desc.dsc_address = string->str_data;
|
||||
}
|
||||
|
||||
EVL_validate(tdbb, Item(nod_cast), (ItemInfo*) node->nod_arg[e_cast_iteminfo],
|
||||
EVL_validate(tdbb, Item(Item::TYPE_CAST), (ItemInfo*) node->nod_arg[e_cast_iteminfo],
|
||||
value, value == NULL || (value->dsc_flags & DSC_null));
|
||||
|
||||
if (value == NULL)
|
||||
|
@ -74,6 +74,7 @@
|
||||
#include "../jrd/sbm.h"
|
||||
#include "../jrd/blb.h"
|
||||
#include "../jrd/blr.h"
|
||||
#include "../dsql/ExprNodes.h"
|
||||
#include "../jrd/blb_proto.h"
|
||||
#include "../jrd/btr_proto.h"
|
||||
#include "../jrd/cmp_proto.h"
|
||||
@ -302,39 +303,37 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
|
||||
SSHORT null = from_null ? -1 : 0;
|
||||
|
||||
if (!null && missing && MOV_compare(missing, from_desc) == 0) {
|
||||
if (!null && missing && MOV_compare(missing, from_desc) == 0)
|
||||
null = -1;
|
||||
}
|
||||
|
||||
USHORT* impure_flags = NULL;
|
||||
const ParameterNode* toParam = ExprNode::as<ParameterNode>(to);
|
||||
|
||||
switch (to->nod_type)
|
||||
if (toParam)
|
||||
{
|
||||
case nod_variable:
|
||||
if (to->nod_arg[e_var_info])
|
||||
{
|
||||
EVL_validate(tdbb,
|
||||
Item(nod_variable, (IPTR) to->nod_arg[e_var_id]),
|
||||
reinterpret_cast<const ItemInfo*>(to->nod_arg[e_var_info]),
|
||||
from_desc, null == -1);
|
||||
}
|
||||
impure_flags = &request->getImpure<impure_value>(
|
||||
to->nod_arg[e_var_variable]->nod_impure)->vlu_flags;
|
||||
break;
|
||||
if (toParam->argInfo)
|
||||
{
|
||||
EVL_validate(tdbb,
|
||||
Item(Item::TYPE_PARAMETER, (IPTR) toParam->message->nod_arg[e_msg_number],
|
||||
toParam->argNumber),
|
||||
toParam->argInfo, from_desc, null == -1);
|
||||
}
|
||||
|
||||
case nod_argument:
|
||||
if (to->nod_arg[e_arg_info])
|
||||
{
|
||||
EVL_validate(tdbb,
|
||||
Item(nod_argument, (IPTR) to->nod_arg[e_arg_message]->nod_arg[e_msg_number],
|
||||
(IPTR) to->nod_arg[e_arg_number]),
|
||||
reinterpret_cast<const ItemInfo*>(to->nod_arg[e_arg_info]),
|
||||
from_desc, null == -1);
|
||||
}
|
||||
impure_flags = request->getImpure<USHORT>(
|
||||
(IPTR) to->nod_arg[e_arg_message]->nod_arg[e_msg_impure_flags] +
|
||||
(sizeof(USHORT) * (IPTR) to->nod_arg[e_arg_number]));
|
||||
break;
|
||||
impure_flags = request->getImpure<USHORT>(
|
||||
(IPTR) toParam->message->nod_arg[e_msg_impure_flags] +
|
||||
(sizeof(USHORT) * toParam->argNumber));
|
||||
}
|
||||
else if (to->nod_type == nod_variable)
|
||||
{
|
||||
if (to->nod_arg[e_var_info])
|
||||
{
|
||||
EVL_validate(tdbb,
|
||||
Item(Item::TYPE_VARIABLE, (IPTR) to->nod_arg[e_var_id]),
|
||||
reinterpret_cast<const ItemInfo*>(to->nod_arg[e_var_info]),
|
||||
from_desc, null == -1);
|
||||
}
|
||||
impure_flags = &request->getImpure<impure_value>(
|
||||
to->nod_arg[e_var_variable]->nod_impure)->vlu_flags;
|
||||
}
|
||||
|
||||
if (impure_flags != NULL)
|
||||
@ -348,12 +347,12 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
{
|
||||
// if necessary and appropriate, use the indicator variable
|
||||
|
||||
if (to->nod_type == nod_argument && to->nod_arg[e_arg_indicator])
|
||||
if (toParam && toParam->argIndicator)
|
||||
{
|
||||
dsc* indicator = EVL_assign_to(tdbb, to->nod_arg[e_arg_indicator]);
|
||||
temp.dsc_dtype = dtype_short;
|
||||
temp.dsc_length = sizeof(SSHORT);
|
||||
temp.dsc_scale = 0;
|
||||
dsc* indicator = EVL_assign_to(tdbb, toParam->argIndicator);
|
||||
temp.dsc_dtype = dtype_short;
|
||||
temp.dsc_length = sizeof(SSHORT);
|
||||
temp.dsc_scale = 0;
|
||||
temp.dsc_sub_type = 0;
|
||||
|
||||
SSHORT len;
|
||||
@ -363,9 +362,8 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
{
|
||||
len = TEXT_LEN(from_desc);
|
||||
}
|
||||
else {
|
||||
else
|
||||
len = 0;
|
||||
}
|
||||
|
||||
temp.dsc_address = (UCHAR *) &len;
|
||||
MOV_move(tdbb, &temp, indicator);
|
||||
@ -374,12 +372,12 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
{
|
||||
temp = *from_desc;
|
||||
temp.dsc_length = TEXT_LEN(to_desc);
|
||||
if (temp.dsc_dtype == dtype_cstring) {
|
||||
|
||||
if (temp.dsc_dtype == dtype_cstring)
|
||||
temp.dsc_length += 1;
|
||||
}
|
||||
else if (temp.dsc_dtype == dtype_varying) {
|
||||
else if (temp.dsc_dtype == dtype_varying)
|
||||
temp.dsc_length += 2;
|
||||
}
|
||||
|
||||
from_desc = &temp;
|
||||
}
|
||||
}
|
||||
@ -472,9 +470,9 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
CLEAR_NULL(record, id);
|
||||
}
|
||||
}
|
||||
else if (to->nod_type == nod_argument && to->nod_arg[e_arg_flag])
|
||||
else if (toParam && toParam->argFlag)
|
||||
{
|
||||
to_desc = EVL_assign_to(tdbb, to->nod_arg[e_arg_flag]);
|
||||
to_desc = EVL_assign_to(tdbb, toParam->argFlag);
|
||||
|
||||
// If the null flag is a string with an effective length of one,
|
||||
// then -1 will not fit. Therefore, store 1 instead.
|
||||
@ -482,6 +480,7 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
if (null && to_desc->dsc_dtype <= dtype_varying)
|
||||
{
|
||||
USHORT minlen;
|
||||
|
||||
switch (to_desc->dsc_dtype)
|
||||
{
|
||||
case dtype_text:
|
||||
@ -494,10 +493,9 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
minlen = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
if (to_desc->dsc_length <= minlen)
|
||||
{
|
||||
null = 1;
|
||||
}
|
||||
}
|
||||
|
||||
temp.dsc_dtype = dtype_short;
|
||||
@ -506,9 +504,10 @@ void EXE_assignment(thread_db* tdbb, const jrd_nod* to, dsc* from_desc, bool fro
|
||||
temp.dsc_sub_type = 0;
|
||||
temp.dsc_address = (UCHAR*) &null;
|
||||
MOV_move(tdbb, &temp, to_desc);
|
||||
if (null && to->nod_arg[e_arg_indicator])
|
||||
|
||||
if (null && toParam->argIndicator)
|
||||
{
|
||||
to_desc = EVL_assign_to(tdbb, to->nod_arg[e_arg_indicator]);
|
||||
to_desc = EVL_assign_to(tdbb, toParam->argIndicator);
|
||||
MOV_move(tdbb, &temp, to_desc);
|
||||
}
|
||||
}
|
||||
|
@ -191,13 +191,6 @@ struct impure_agg_sort
|
||||
|
||||
// Various field positions
|
||||
|
||||
const int e_arg_flag = 0;
|
||||
const int e_arg_indicator = 1;
|
||||
const int e_arg_message = 2;
|
||||
const int e_arg_number = 3;
|
||||
const int e_arg_info = 4;
|
||||
const int e_arg_length = 5;
|
||||
|
||||
const int e_msg_number = 0;
|
||||
const int e_msg_format = 1;
|
||||
const int e_msg_impure_flags = 2;
|
||||
@ -540,21 +533,28 @@ typedef Firebird::SortedArray<ExternalAccess, Firebird::EmptyStorage<ExternalAcc
|
||||
// The three structs below are used for domains DEFAULT and constraints in PSQL
|
||||
struct Item
|
||||
{
|
||||
Item(nod_t aType, UCHAR aSubType, USHORT aIndex)
|
||||
enum Type
|
||||
{
|
||||
TYPE_VARIABLE,
|
||||
TYPE_PARAMETER,
|
||||
TYPE_CAST
|
||||
};
|
||||
|
||||
Item(Type aType, UCHAR aSubType, USHORT aIndex)
|
||||
: type(aType),
|
||||
subType(aSubType),
|
||||
index(aIndex)
|
||||
{
|
||||
}
|
||||
|
||||
Item(nod_t aType, USHORT aIndex = 0)
|
||||
Item(Type aType, USHORT aIndex = 0)
|
||||
: type(aType),
|
||||
subType(0),
|
||||
index(aIndex)
|
||||
{
|
||||
}
|
||||
|
||||
nod_t type;
|
||||
Type type;
|
||||
UCHAR subType;
|
||||
USHORT index;
|
||||
|
||||
|
@ -51,18 +51,18 @@ NODE(nod_exec_stmt, exec_stmt, "EXECUTE STATEMENT")
|
||||
NODE(nod_dcl_cursor, declare_cursor, "DECLARE CURSOR")
|
||||
NODE(nod_cursor_stmt, cursor_stmt, "CURSOR STATEMENT")
|
||||
NODE(nod_continue_loop, continue_loop, "")
|
||||
NODE(nod_src_info, source_info, "")
|
||||
NODE(nod_init_variable, init_variable, "")
|
||||
|
||||
NODE(nod_set_generator, set_generator, "")
|
||||
NODE(nod_set_generator2, set_generator, "")
|
||||
|
||||
NODE(nod_argument, argument, "")
|
||||
NODE(nod_variable, variable, "")
|
||||
NODE(nod_dbkey, dbkey, "ROWID")
|
||||
NODE(nod_field, field, "")
|
||||
NODE(nod_from, from, "")
|
||||
NODE(nod_literal, literal, "")
|
||||
NODE(nod_scalar, scalar, "")
|
||||
NODE(nod_gen_id, recnum, "")
|
||||
NODE(nod_prot_mask, prot_mask, "")
|
||||
NODE(nod_upcase, upcase, "UPPER")
|
||||
NODE(nod_lock_state, lock_state, "")
|
||||
@ -72,11 +72,8 @@ NODE(nod_trim, trim, "")
|
||||
NODE(nod_cast, cast, "CAST")
|
||||
NODE(nod_rec_version, record_version, "RECORD VERSION")
|
||||
NODE(nod_extract, extract, "EXTRACT")
|
||||
NODE(nod_gen_id2, recnum, "")
|
||||
NODE(nod_lowcase, lowcase, "LOWER")
|
||||
NODE(nod_strlen, strlen, "STRLEN")
|
||||
NODE(nod_src_info, source_info, "")
|
||||
NODE(nod_init_variable, init_variable, "")
|
||||
NODE(nod_domain_validation, domain_validation, "")
|
||||
NODE(nod_derived_expr, derived_expr, "derived_expr")
|
||||
|
||||
|
@ -118,9 +118,6 @@ bool JrdNodeVisitor::visitChildren(const JrdNode& node)
|
||||
return call(exprNode);
|
||||
}
|
||||
|
||||
case nod_argument:
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
case nod_literal:
|
||||
case nod_null:
|
||||
case nod_variable:
|
||||
@ -413,9 +410,6 @@ bool UnmappedNodeGetter::visit(const JrdNode& node)
|
||||
case nod_field:
|
||||
break;
|
||||
|
||||
case nod_argument:
|
||||
case nod_gen_id:
|
||||
case nod_gen_id2:
|
||||
case nod_literal:
|
||||
case nod_null:
|
||||
case nod_variable:
|
||||
@ -1897,7 +1891,7 @@ static USHORT distribute_equalities(BoolExprNodeStack& org_stack, CompilerScratc
|
||||
|
||||
if (node2->nod_type != nod_literal &&
|
||||
node2->nod_type != nod_variable &&
|
||||
node2->nod_type != nod_argument)
|
||||
!ExprNode::is<ParameterNode>(node2))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -1576,7 +1576,8 @@ static jrd_nod* par_message(thread_db* tdbb, CompilerScratch* csb)
|
||||
csb->csb_dbg_info.argInfoToName.get(
|
||||
Firebird::ArgumentInfo(csb->csb_msg_number, index / 2), itemInfo.name);
|
||||
|
||||
csb->csb_map_item_info.put(Item(nod_argument, csb->csb_msg_number, index), itemInfo);
|
||||
csb->csb_map_item_info.put(Item(Item::TYPE_PARAMETER, csb->csb_msg_number, index),
|
||||
itemInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1986,19 +1987,26 @@ void PAR_procedure_parms(thread_db* tdbb, CompilerScratch* csb, jrd_prc* procedu
|
||||
Parameter* parameter = procedure->prc_input_fields[inputCount - n];
|
||||
asgn->nod_arg[asgn_arg1] = CMP_clone_node(tdbb, csb, parameter->prm_default_value);
|
||||
}
|
||||
else {
|
||||
else
|
||||
asgn->nod_arg[asgn_arg1] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
}
|
||||
jrd_nod* prm = asgn->nod_arg[asgn_arg2] = PAR_make_node(tdbb, e_arg_length);
|
||||
prm->nod_type = nod_argument;
|
||||
prm->nod_count = 1;
|
||||
prm->nod_arg[e_arg_message] = message;
|
||||
prm->nod_arg[e_arg_number] = (jrd_nod*)(IPTR) i++;
|
||||
jrd_nod* prm_f = prm->nod_arg[e_arg_flag] = PAR_make_node(tdbb, e_arg_length);
|
||||
prm_f->nod_type = nod_argument;
|
||||
prm_f->nod_count = 0;
|
||||
prm_f->nod_arg[e_arg_message] = message;
|
||||
prm_f->nod_arg[e_arg_number] = (jrd_nod*)(IPTR) i++;
|
||||
|
||||
ParameterNode* paramNode = FB_NEW(csb->csb_pool) ParameterNode(csb->csb_pool);
|
||||
paramNode->message = message;
|
||||
paramNode->argNumber = i++;
|
||||
|
||||
ParameterNode* paramFlagNode = FB_NEW(csb->csb_pool) ParameterNode(csb->csb_pool);
|
||||
paramFlagNode->message = message;
|
||||
paramFlagNode->argNumber = i++;
|
||||
|
||||
jrd_nod* legacyNode = asgn->nod_arg[asgn_arg2] = PAR_make_node(tdbb, 1);
|
||||
legacyNode->nod_type = nod_class_exprnode_jrd;
|
||||
legacyNode->nod_count = 0;
|
||||
legacyNode->nod_arg[0] = reinterpret_cast<jrd_nod*>(paramNode);
|
||||
|
||||
legacyNode = paramNode->argFlag = PAR_make_node(tdbb, 1);
|
||||
legacyNode->nod_type = nod_class_exprnode_jrd;
|
||||
legacyNode->nod_count = 0;
|
||||
legacyNode->nod_arg[0] = reinterpret_cast<jrd_nod*>(paramFlagNode);
|
||||
}
|
||||
}
|
||||
else if (input_flag ? inputCount : procedure->prc_output_fields.getCount())
|
||||
@ -2627,29 +2635,17 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
break;
|
||||
}
|
||||
|
||||
case blr_gen_id:
|
||||
case blr_set_generator:
|
||||
{
|
||||
Firebird::MetaName name;
|
||||
|
||||
PAR_name(csb, name);
|
||||
|
||||
const SLONG tmp = MET_lookup_generator(tdbb, name.c_str());
|
||||
if (tmp < 0) {
|
||||
if (tmp < 0)
|
||||
PAR_error(csb, Arg::Gds(isc_gennotdef) << Arg::Str(name));
|
||||
}
|
||||
|
||||
node->nod_arg[e_gen_id] = (jrd_nod*)(IPTR) tmp;
|
||||
node->nod_arg[e_gen_value] = PAR_parse_node(tdbb, csb, VALUE);
|
||||
|
||||
// CVC: There're thousand ways to go wrong, but I don't see any value
|
||||
// in posting dependencies with set generator since it's DDL, so I will
|
||||
// track only gen_id() in both dialects.
|
||||
if ((blr_operator == blr_gen_id) && (csb->csb_g_flags & csb_get_dependencies))
|
||||
{
|
||||
CompilerScratch::Dependency dependency(obj_generator);
|
||||
dependency.number = tmp;
|
||||
csb->csb_dependencies.push(dependency);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2712,7 +2708,7 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
if (itemInfo.isSpecial())
|
||||
{
|
||||
csb->csb_dbg_info.varIndexToName.get(n, itemInfo.name);
|
||||
csb->csb_map_item_info.put(Item(nod_variable, n), itemInfo);
|
||||
csb->csb_map_item_info.put(Item(Item::TYPE_VARIABLE, n), itemInfo);
|
||||
}
|
||||
|
||||
if (itemInfo.explicitCollation)
|
||||
@ -2734,51 +2730,6 @@ jrd_nod* PAR_parse_node(thread_db* tdbb, CompilerScratch* csb, USHORT expected)
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_parameter:
|
||||
case blr_parameter2:
|
||||
case blr_parameter3:
|
||||
{
|
||||
jrd_nod* message = NULL;
|
||||
n = (USHORT) csb->csb_blr_reader.getByte();
|
||||
if (n >= csb->csb_rpt.getCount() || !(message = csb->csb_rpt[n].csb_message))
|
||||
{
|
||||
PAR_error(csb, Arg::Gds(isc_badmsgnum));
|
||||
}
|
||||
node->nod_arg[e_arg_message] = message;
|
||||
n = csb->csb_blr_reader.getWord();
|
||||
node->nod_arg[e_arg_number] = (jrd_nod*) (IPTR) n;
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
if (n >= format->fmt_count)
|
||||
PAR_error(csb, Arg::Gds(isc_badparnum));
|
||||
if (blr_operator != blr_parameter)
|
||||
{
|
||||
jrd_nod* temp = PAR_make_node(tdbb, e_arg_length);
|
||||
node->nod_arg[e_arg_flag] = temp;
|
||||
node->nod_count = 1;
|
||||
temp->nod_count = 0;
|
||||
temp->nod_type = nod_argument;
|
||||
temp->nod_arg[e_arg_message] = message;
|
||||
n = csb->csb_blr_reader.getWord();
|
||||
temp->nod_arg[e_arg_number] = (jrd_nod*) (IPTR) n;
|
||||
if (n >= format->fmt_count)
|
||||
PAR_error(csb, Arg::Gds(isc_badparnum));
|
||||
}
|
||||
if (blr_operator == blr_parameter3)
|
||||
{
|
||||
jrd_nod* temp = PAR_make_node(tdbb, e_arg_length);
|
||||
node->nod_arg[e_arg_indicator] = temp;
|
||||
node->nod_count = 2;
|
||||
temp->nod_count = 0;
|
||||
temp->nod_type = nod_argument;
|
||||
temp->nod_arg[e_arg_message] = message;
|
||||
n = csb->csb_blr_reader.getWord();
|
||||
temp->nod_arg[e_arg_number] = (jrd_nod*) (IPTR) n;
|
||||
if (n >= format->fmt_count)
|
||||
PAR_error(csb, Arg::Gds(isc_badparnum));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case blr_stall:
|
||||
break;
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "../../jrd/jrd.h"
|
||||
#include "../../jrd/tra.h"
|
||||
#include "../../jrd/DataTypeUtil.h"
|
||||
#include "../../dsql/ExprNodes.h"
|
||||
#include "../../jrd/evl_proto.h"
|
||||
#include "../../jrd/intl_proto.h"
|
||||
#include "../../jrd/mov_proto.h"
|
||||
@ -377,31 +378,31 @@ void TraceProcedureImpl::JrdParamsImpl::fillParams()
|
||||
dsc desc;
|
||||
|
||||
const jrd_nod* const prm = (*ptr)->nod_arg[e_asgn_to];
|
||||
const ParameterNode* param = ExprNode::as<ParameterNode>(prm);
|
||||
|
||||
if (param)
|
||||
{
|
||||
//const impure_value* impure = request->getImpure<impure_value>(prm->nod_impure)
|
||||
const jrd_nod* message = param->message;
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
const int arg_number = param->argNumber;
|
||||
|
||||
desc = format->fmt_desc[arg_number];
|
||||
from_desc = &desc;
|
||||
from_desc->dsc_address = const_cast<jrd_req*>(m_request)->getImpure<UCHAR>(
|
||||
message->nod_impure + (IPTR) desc.dsc_address);
|
||||
|
||||
// handle null flag if present
|
||||
if (param->argFlag)
|
||||
{
|
||||
const dsc* flag = EVL_expr(tdbb, param->argFlag);
|
||||
if (MOV_get_long(flag, 0))
|
||||
from_desc->dsc_flags |= DSC_null;
|
||||
}
|
||||
}
|
||||
|
||||
switch (prm->nod_type)
|
||||
{
|
||||
case nod_argument:
|
||||
{
|
||||
//const impure_value* impure = request->getImpure<impure_value>(prm->nod_impure)
|
||||
const jrd_nod* message = prm->nod_arg[e_arg_message];
|
||||
const Format* format = (Format*) message->nod_arg[e_msg_format];
|
||||
const int arg_number = (int) (IPTR) prm->nod_arg[e_arg_number];
|
||||
|
||||
desc = format->fmt_desc[arg_number];
|
||||
from_desc = &desc;
|
||||
from_desc->dsc_address = const_cast<jrd_req*>(m_request)->getImpure<UCHAR>(
|
||||
message->nod_impure + (IPTR) desc.dsc_address);
|
||||
|
||||
// handle null flag if present
|
||||
if (prm->nod_arg[e_arg_flag])
|
||||
{
|
||||
const dsc* flag = EVL_expr(tdbb, prm->nod_arg[e_arg_flag]);
|
||||
if (MOV_get_long(flag, 0)) {
|
||||
from_desc->dsc_flags |= DSC_null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case nod_variable:
|
||||
{
|
||||
impure_value* impure = const_cast<jrd_req*>(m_request)->getImpure<impure_value>(
|
||||
|
@ -110,9 +110,9 @@ static const VERB verbs[] =
|
||||
PAIR(nod_class_exprnode_jrd, blr_agg_average_distinct, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_agg_list, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_agg_list_distinct, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_argument, blr_parameter, e_arg_length, 0, VALUE, VALUE),
|
||||
PAIR(nod_argument, blr_parameter2, e_arg_length, 0, VALUE, VALUE),
|
||||
PAIR(nod_argument, blr_parameter3, e_arg_length, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_parameter, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_parameter2, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_parameter3, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_variable, blr_variable, e_var_length, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_user_name, 1, 0, VALUE, VALUE),
|
||||
PAIR2(nod_average, blr_average, e_stat_length, 2, VALUE, VALUE),
|
||||
@ -135,7 +135,7 @@ static const VERB verbs[] =
|
||||
PAIR(nod_null, blr_null, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_multiply, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_negate, 1, 0, VALUE, VALUE),
|
||||
PAIR2(nod_gen_id, blr_gen_id, e_gen_length, 1, VALUE, VALUE),
|
||||
PAIR(nod_class_exprnode_jrd, blr_gen_id, 1, 0, VALUE, VALUE),
|
||||
PAIR(nod_prot_mask, blr_prot_mask, e_pro_length, 2, VALUE, VALUE),
|
||||
PAIR(nod_upcase, blr_upcase, 1, 1, VALUE, VALUE),
|
||||
PAIR(nod_lock_state, blr_lock_state, 1, 1, VALUE, VALUE),
|
||||
|
Loading…
Reference in New Issue
Block a user