diff --git a/src/dsql/AggNodes.cpp b/src/dsql/AggNodes.cpp index a90c0dcb0d..f21869da05 100644 --- a/src/dsql/AggNodes.cpp +++ b/src/dsql/AggNodes.cpp @@ -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); diff --git a/src/dsql/AggNodes.h b/src/dsql/AggNodes.h index 624f9e0c97..ba0191caeb 100644 --- a/src/dsql/AggNodes.h +++ b/src/dsql/AggNodes.h @@ -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); diff --git a/src/dsql/ExprNodes.cpp b/src/dsql/ExprNodes.cpp index c433e85e9c..8d37209b9d 100644 --- a/src/dsql/ExprNodes.cpp +++ b/src/dsql/ExprNodes.cpp @@ -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 regGenIdNode(blr_gen_id); + +GenIdNode::GenIdNode(MemoryPool& pool, bool aDialect1, const MetaName& aName, dsql_nod* aArg) + : TypedNode(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& 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(); + 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(); + 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(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 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(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 regParameterNode(blr_parameter); +static RegisterNode regParameterNode2(blr_parameter2); +static RegisterNode regParameterNode3(blr_parameter3); + +ParameterNode::ParameterNode(MemoryPool& pool) + : TypedNode(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(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(indicatorNode); + } + + return node; +} + +void ParameterNode::print(string& text, Array& 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(); + + 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(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( + 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( + (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 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 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(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 args; diff --git a/src/dsql/ExprNodes.h b/src/dsql/ExprNodes.h index dcd648f710..77828724dc 100644 --- a/src/dsql/ExprNodes.h +++ b/src/dsql/ExprNodes.h @@ -31,6 +31,8 @@ class SysFunction; namespace Jrd { +struct ItemInfo; + class ArithmeticNode : public TypedNode { @@ -43,10 +45,11 @@ public: virtual void print(Firebird::string& text, Firebird::Array& 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& 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& 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 +{ +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& 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 arg; + SLONG id; +}; + + class InternalInfoNode : public TypedNode { 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& 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 +{ +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& 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 message; + USHORT argNumber; + NestConst argFlag; + NestConst argIndicator; + NestConst argInfo; +}; + + class SubstringSimilarNode : public TypedNode { public: @@ -352,10 +460,11 @@ public: virtual void print(Firebird::string& text, Firebird::Array& 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& 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*/) { diff --git a/src/dsql/Nodes.h b/src/dsql/Nodes.h index d9865846a4..e9df209725 100644 --- a/src/dsql/Nodes.h +++ b/src/dsql/Nodes.h @@ -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; diff --git a/src/dsql/Parser.h b/src/dsql/Parser.h index 720b56174e..8543b9bbd3 100644 --- a/src/dsql/Parser.h +++ b/src/dsql/Parser.h @@ -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); diff --git a/src/dsql/Visitors.h b/src/dsql/Visitors.h index 2583789875..c936ee3444 100644 --- a/src/dsql/Visitors.h +++ b/src/dsql/Visitors.h @@ -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::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::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]); diff --git a/src/dsql/WinNodes.cpp b/src/dsql/WinNodes.cpp index ebdf793f7c..baa458f7ae 100644 --- a/src/dsql/WinNodes.cpp +++ b/src/dsql/WinNodes.cpp @@ -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); diff --git a/src/dsql/WinNodes.h b/src/dsql/WinNodes.h index bde2402b23..c36215f734 100644 --- a/src/dsql/WinNodes.h +++ b/src/dsql/WinNodes.h @@ -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; diff --git a/src/dsql/dsql.cpp b/src/dsql/dsql.cpp index a4b00afbcc..6bbd19417d 100644 --- a/src/dsql/dsql.cpp +++ b/src/dsql/dsql.cpp @@ -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(node)->dsqlParameter; const dsql_par* null = parameter->par_null; dsc desc; diff --git a/src/dsql/gen.cpp b/src/dsql/gen.cpp index f540e50bee..fa49846aad 100644 --- a/src/dsql/gen.cpp +++ b/src/dsql/gen.cpp @@ -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()); } diff --git a/src/dsql/gen_proto.h b/src/dsql/gen_proto.h index 83c561bff3..3bc13f923d 100644 --- a/src/dsql/gen_proto.h +++ b/src/dsql/gen_proto.h @@ -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*); diff --git a/src/dsql/make.cpp b/src/dsql/make.cpp index af013e70ec..26fe8f5f11 100644 --- a/src/dsql/make.cpp +++ b/src/dsql/make.cpp @@ -402,7 +402,7 @@ void MAKE_desc(DsqlCompilerScratch* dsqlScratch, dsc* desc, dsql_nod* node, dsql case nod_class_exprnode: { ValueExprNode* exprNode = reinterpret_cast(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"; diff --git a/src/dsql/node.h b/src/dsql/node.h index fde32d2726..58a2b0b99b 100644 --- a/src/dsql/node.h +++ b/src/dsql/node.h @@ -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__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, diff --git a/src/dsql/parse.y b/src/dsql/parse.y index 5ef0a2dcf9..e7769293b3 100644 --- a/src/dsql/parse.y +++ b/src/dsql/parse.y @@ -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; } diff --git a/src/dsql/pass1.cpp b/src/dsql/pass1.cpp index 1a893336b0..417624a89d 100644 --- a/src/dsql/pass1.cpp +++ b/src/dsql/pass1.cpp @@ -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(paramNode); + + *ptr = p_node; + dsql_par* parameter = paramNode->dsqlParameter = MAKE_parameter( + dsqlScratch->getStatement()->getReceiveMsg(), true, true, 0, NULL); - p_node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index; - p_node->nod_arg[e_par_parameter] = (dsql_nod*) parameter; + paramNode->dsqlParameterIndex = parameter->par_index; + MAKE_desc_from_field(¶meter->par_desc, field); parameter->par_name = parameter->par_alias = field->fld_name.c_str(); parameter->par_rel_name = procedure->prc_name.identifier.c_str(); @@ -2963,16 +2939,13 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_ return PASS1_node_match(map1->map_node, map2->map_node, ignore_map_cast); } - case nod_gen_id: - case nod_gen_id2: case nod_cast: - if (node1->nod_arg[0] != node2->nod_arg[0]) { + if (node1->nod_arg[0] != node2->nod_arg[0]) return false; - } - if (node1->nod_count == 2) { + if (node1->nod_count == 2) return PASS1_node_match(node1->nod_arg[1], node2->nod_arg[1], ignore_map_cast); - } + return true; case nod_variable: @@ -2992,14 +2965,6 @@ bool PASS1_node_match(const dsql_nod* node1, const dsql_nod* node2, bool ignore_ return true; } - case nod_parameter: - { - // Parameters are equal when there index is the same - const dsql_par* parameter1 = (dsql_par*) node1->nod_arg[e_par_parameter]; - const dsql_par* parameter2 = (dsql_par*) node2->nod_arg[e_par_parameter]; - return (parameter1->par_index == parameter2->par_index); - } - case nod_derived_table: { const dsql_ctx* ctx1 = (dsql_ctx*) node1->nod_arg[e_derived_table_context]; @@ -3618,7 +3583,7 @@ static dsql_nod* pass1_cursor_reference( DsqlCompilerScratch* dsqlScratch, const temp->nod_arg[0] = relation_node; ComparativeBoolNode* eqlNode = FB_NEW(pool) ComparativeBoolNode(pool, - blr_eql, MAKE_node(nod_dbkey, 1), MAKE_node(nod_parameter, e_par_count)); + blr_eql, MAKE_node(nod_dbkey, 1), MAKE_node(nod_class_exprnode, 1)); dsql_nod* node = MAKE_node(nod_class_exprnode, 1); node->nod_arg[0] = reinterpret_cast(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(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(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(paramNode); + paramNode->dsqlParameterIndex = parameter->par_index; + paramNode->dsqlParameter = parameter; + parameter->par_desc = rv_source->par_desc; rse->nod_arg[e_rse_boolean] = PASS1_compose(rse->nod_arg[e_rse_boolean], node, blr_and); @@ -4808,7 +4781,6 @@ static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_no case nod_dbkey: case nod_field: case nod_null: - case nod_parameter: case nod_variable: return NULL; @@ -4821,6 +4793,7 @@ static dsql_nod* pass1_hidden_variable(DsqlCompilerScratch* dsqlScratch, dsql_no case ExprNode::TYPE_CURRENT_ROLE: case ExprNode::TYPE_CURRENT_USER: case ExprNode::TYPE_INTERNAL_INFO: + case ExprNode::TYPE_PARAMETER: return NULL; } break; @@ -6349,6 +6322,8 @@ static dsql_rel* pass1_base_table( DsqlCompilerScratch* dsqlScratch, const dsql_ **/ static dsql_nod* pass1_returning(DsqlCompilerScratch* dsqlScratch, const dsql_nod* input) { + thread_db* tdbb = JRD_get_thread_data(); + DEV_BLKCHK(dsqlScratch, dsql_type_req); DEV_BLKCHK(input, dsql_type_nod); @@ -6419,10 +6394,14 @@ static dsql_nod* pass1_returning(DsqlCompilerScratch* dsqlScratch, const dsql_no MAKE_desc(dsqlScratch, ¶meter->par_desc, *src, NULL); parameter->par_desc.dsc_flags |= DSC_nullable; - dsql_nod* p_node = MAKE_node(nod_parameter, e_par_count); + ParameterNode* paramNode = FB_NEW(*tdbb->getDefaultPool()) ParameterNode( + *tdbb->getDefaultPool()); + paramNode->dsqlParameterIndex = parameter->par_index; + paramNode->dsqlParameter = parameter; + + dsql_nod* p_node = MAKE_node(nod_class_exprnode, 1); p_node->nod_count = 0; - p_node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index; - p_node->nod_arg[e_par_parameter] = (dsql_nod*) parameter; + p_node->nod_arg[0] = reinterpret_cast(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(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(*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(in_node->nod_arg[0]); - return exprNode->setParameterType(dsqlScratch, node, force_varchar); + return exprNode->setParameterType(dsqlScratch, in_node, node, force_varchar); } - case nod_parameter: - { - if (!node) - in_node->nod_desc.makeNullString(); - else - { - MAKE_desc(dsqlScratch, &in_node->nod_desc, node, NULL); - - if (tdbb->getCharSet() != CS_NONE && tdbb->getCharSet() != CS_BINARY) - { - const USHORT fromCharSet = in_node->nod_desc.getCharSet(); - const USHORT toCharSet = (fromCharSet == CS_NONE || fromCharSet == CS_BINARY) ? - fromCharSet : tdbb->getCharSet(); - - if (in_node->nod_desc.dsc_dtype <= dtype_any_text) - { - int diff = 0; - switch (in_node->nod_desc.dsc_dtype) - { - case dtype_varying: - diff = sizeof(USHORT); - break; - case dtype_cstring: - diff = 1; - break; - } - in_node->nod_desc.dsc_length -= diff; - - if (toCharSet != fromCharSet) - { - const USHORT fromCharSetBPC = METD_get_charset_bpc( - dsqlScratch->getTransaction(), fromCharSet); - const USHORT toCharSetBPC = METD_get_charset_bpc( - dsqlScratch->getTransaction(), toCharSet); - - in_node->nod_desc.setTextType(INTL_CS_COLL_TO_TTYPE(toCharSet, - (fromCharSet == toCharSet ? INTL_GET_COLLATE(&in_node->nod_desc) : 0))); - - in_node->nod_desc.dsc_length = - UTLD_char_length_to_byte_length(in_node->nod_desc.dsc_length / fromCharSetBPC, toCharSetBPC); - } - - in_node->nod_desc.dsc_length += diff; - } - else if (in_node->nod_desc.dsc_dtype == dtype_blob && - in_node->nod_desc.dsc_sub_type == isc_blob_text && - fromCharSet != CS_NONE && fromCharSet != CS_BINARY) - { - in_node->nod_desc.setTextType(toCharSet); - } - } - } - - dsql_par* parameter = (dsql_par*) in_node->nod_arg[e_par_parameter]; - - if (!parameter) - { - parameter = MAKE_parameter(dsqlScratch->getStatement()->getSendMsg(), true, true, - (USHORT)(IPTR) in_node->nod_arg[e_par_index], NULL); - in_node->nod_arg[e_par_parameter] = (dsql_nod*) parameter; - in_node->nod_arg[e_par_index] = (dsql_nod*) (IPTR) parameter->par_index; - } - - // In case of RETURNING in MERGE and UPDATE OR INSERT, a single parameter is used in - // more than one place. So we save it to use below. - dsc oldDesc = parameter->par_desc; - bool hasOldDesc = parameter->par_node != NULL; - - parameter->par_desc = in_node->nod_desc; - parameter->par_node = in_node; - - // Parameters should receive precisely the data that the user - // passes in. Therefore for text strings lets use varying - // strings to insure that we don't add trailing blanks. - - // However, there are situations this leads to problems - so - // we use the force_varchar parameter to prevent this - // datatype assumption from occuring. - - if (force_varchar) - { - if (parameter->par_desc.dsc_dtype == dtype_text) - { - parameter->par_desc.dsc_dtype = dtype_varying; - // The error msgs is inaccurate, but causing dsc_length - // to be outsise range can be worse. - if (parameter->par_desc.dsc_length > MAX_COLUMN_SIZE - sizeof(USHORT)) - { - ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-204) << - //Arg::Gds(isc_dsql_datatype_err) - Arg::Gds(isc_imp_exc)); - //Arg::Gds(isc_field_name) << Arg::Str(parameter->par_name) - } - - parameter->par_desc.dsc_length += sizeof(USHORT); - } - else if (parameter->par_desc.dsc_dtype > dtype_any_text) - { - const USHORT toCharSetBPC = METD_get_charset_bpc( - dsqlScratch->getTransaction(), tdbb->getCharSet()); - - // The LIKE & similar parameters must be varchar type - // strings - so force this parameter to be varchar - // and take a guess at a good length for it. - parameter->par_desc.dsc_dtype = dtype_varying; - parameter->par_desc.dsc_length = LIKE_PARAM_LEN * toCharSetBPC + - sizeof(USHORT); - parameter->par_desc.dsc_sub_type = 0; - parameter->par_desc.dsc_scale = 0; - parameter->par_desc.dsc_ttype() = ttype_dynamic; - } - } - - if (hasOldDesc) - { - dsc thisDesc = parameter->par_desc; - const dsc* args[] = {&oldDesc, &thisDesc}; - DSqlDataTypeUtil(dsqlScratch).makeFromList(¶meter->par_desc, - parameter->par_name.c_str(), 2, args); - } - - return true; - } - case nod_cast: { dsql_nod* par_node = in_node->nod_arg[e_cast_source]; dsql_fld* field = (dsql_fld*) in_node->nod_arg[e_cast_target]; - if (par_node->nod_type == nod_parameter) + ParameterNode* paramNode; + + if ((paramNode = ExprNode::as(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(); + 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; diff --git a/src/jrd/Optimizer.cpp b/src/jrd/Optimizer.cpp index 41077156e3..fe3ea41cff 100644 --- a/src/jrd/Optimizer.cpp +++ b/src/jrd/Optimizer.cpp @@ -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); diff --git a/src/jrd/blb.cpp b/src/jrd/blb.cpp index 2381b935b1..62942e5c38 100644 --- a/src/jrd/blb.cpp +++ b/src/jrd/blb.cpp @@ -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(field)) + break; + // fall into + default: BUGCHECK(199); // msg 199 expected field node } diff --git a/src/jrd/cmp.cpp b/src/jrd/cmp.cpp index 0dd78c985e..826ba37bfc 100644 --- a/src/jrd/cmp.cpp +++ b/src/jrd/cmp.cpp @@ -169,7 +169,6 @@ static void pass1_modify(thread_db*, CompilerScratch*, jrd_nod*); static bool pass1_store(thread_db*, CompilerScratch*, jrd_nod*); static RelationSourceNode* pass1_update(thread_db*, CompilerScratch*, jrd_rel*, const trig_vec*, USHORT, USHORT, SecurityClass::flags_t, jrd_rel*, USHORT); -static jrd_nod* pass2_validation(thread_db*, CompilerScratch*, const Item&); static void post_trigger_access(CompilerScratch*, jrd_rel*, ExternalAccess::exa_act, jrd_rel*); #ifdef CMP_DEBUG @@ -209,7 +208,7 @@ jrd_nod* CMP_clone_node_opt(thread_db* tdbb, CompilerScratch* csb, jrd_nod* node DEV_BLKCHK(csb, type_csb); DEV_BLKCHK(node, type_nod); - if (node->nod_type == nod_argument) + if (ExprNode::is(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(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(, 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(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(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(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(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(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(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: diff --git a/src/jrd/cmp_proto.h b/src/jrd/cmp_proto.h index 3fa63f6e8a..6495d9be57 100644 --- a/src/jrd/cmp_proto.h +++ b/src/jrd/cmp_proto.h @@ -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&); diff --git a/src/jrd/evl.cpp b/src/jrd/evl.cpp index 8d67211415..032b0491ed 100644 --- a/src/jrd/evl.cpp +++ b/src/jrd/evl.cpp @@ -146,10 +146,6 @@ dsc* EVL_assign_to(thread_db* tdbb, const jrd_nod* node) * destination node of an assignment. * **************************************/ - const dsc* desc; - const Format* format; - const jrd_nod* message; - Record* record; SET_TDBB(tdbb); @@ -161,33 +157,43 @@ dsc* EVL_assign_to(thread_db* tdbb, const jrd_nod* node) // The only nodes that can be assigned to are: argument, field and variable. int arg_number; + const dsc* desc; + const Format* format; + const jrd_nod* message; + Record* record; + const ParameterNode* paramNode; - switch (node->nod_type) + if ((paramNode = ExprNode::as(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( 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( - 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( - (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(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(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) diff --git a/src/jrd/exe.cpp b/src/jrd/exe.cpp index 420469e74e..6e47ef2b69 100644 --- a/src/jrd/exe.cpp +++ b/src/jrd/exe.cpp @@ -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(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(to->nod_arg[e_var_info]), - from_desc, null == -1); - } - impure_flags = &request->getImpure( - 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(to->nod_arg[e_arg_info]), - from_desc, null == -1); - } - impure_flags = request->getImpure( - (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( + (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(to->nod_arg[e_var_info]), + from_desc, null == -1); + } + impure_flags = &request->getImpure( + 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); } } diff --git a/src/jrd/exe.h b/src/jrd/exe.h index 42738c2ae7..3fbf6d017e 100644 --- a/src/jrd/exe.h +++ b/src/jrd/exe.h @@ -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::SortedArraynod_type != nod_literal && node2->nod_type != nod_variable && - node2->nod_type != nod_argument) + !ExprNode::is(node2)) { continue; } diff --git a/src/jrd/par.cpp b/src/jrd/par.cpp index cdfefb3c02..62b1afa718 100644 --- a/src/jrd/par.cpp +++ b/src/jrd/par.cpp @@ -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(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(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; diff --git a/src/jrd/trace/TraceObjects.cpp b/src/jrd/trace/TraceObjects.cpp index 35350e1348..337e6197fb 100644 --- a/src/jrd/trace/TraceObjects.cpp +++ b/src/jrd/trace/TraceObjects.cpp @@ -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(prm); + + if (param) + { + //const impure_value* impure = request->getImpure(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(m_request)->getImpure( + 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(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(m_request)->getImpure( - 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(m_request)->getImpure( diff --git a/src/misc/blrtable.cpp b/src/misc/blrtable.cpp index 362074912b..d2f1c197bd 100644 --- a/src/misc/blrtable.cpp +++ b/src/misc/blrtable.cpp @@ -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),