8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 21:23:04 +01:00

Refactor parameters and GEN_ID.

This commit is contained in:
asfernandes 2010-10-09 01:57:37 +00:00
parent 9bf9ca4ef7
commit 4d00fec2d6
28 changed files with 1005 additions and 803 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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*/)
{

View File

@ -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;

View File

@ -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);

View File

@ -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]);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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());
}

View File

@ -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*);

View File

@ -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";

View File

@ -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,

View File

@ -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;
}

View File

@ -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(&parameter->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, &parameter->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(&parameter->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;

View File

@ -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);

View File

@ -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
}

View File

@ -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:

View File

@ -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&);

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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")

View File

@ -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;
}

View File

@ -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;

View File

@ -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>(

View File

@ -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),