Turn a cursor reference into a record selection expression.
| 10117 | |
| 10118 | // Turn a cursor reference into a record selection expression. |
| 10119 | static dsql_ctx* dsqlPassCursorContext(DsqlCompilerScratch* dsqlScratch, const MetaName& cursor, |
| 10120 | const RelationSourceNode* relation_name) |
| 10121 | { |
| 10122 | DEV_BLKCHK(dsqlScratch, dsql_type_req); |
| 10123 | |
| 10124 | const MetaName& relName = relation_name->dsqlName; |
| 10125 | |
| 10126 | // this function must throw an error if no cursor was found |
| 10127 | const DeclareCursorNode* node = PASS1_cursor_name(dsqlScratch, cursor, |
| 10128 | DeclareCursorNode::CUR_TYPE_ALL, true); |
| 10129 | fb_assert(node); |
| 10130 | |
| 10131 | const RseNode* nodeRse = nodeAs<RseNode>(node->rse); |
| 10132 | fb_assert(nodeRse); |
| 10133 | |
| 10134 | if (nodeRse->dsqlDistinct) |
| 10135 | { |
| 10136 | // cursor with DISTINCT is not updatable |
| 10137 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-510) << |
| 10138 | Arg::Gds(isc_dsql_cursor_update_err) << cursor); |
| 10139 | } |
| 10140 | |
| 10141 | NestConst<RecSourceListNode> temp = nodeRse->dsqlStreams; |
| 10142 | dsql_ctx* context = NULL; |
| 10143 | |
| 10144 | for (auto& recSource : temp->items) |
| 10145 | { |
| 10146 | if (auto relNode = nodeAs<RelationSourceNode>(recSource)) |
| 10147 | { |
| 10148 | dsql_ctx* candidate = relNode->dsqlContext; |
| 10149 | DEV_BLKCHK(candidate, dsql_type_ctx); |
| 10150 | const dsql_rel* relation = candidate->ctx_relation; |
| 10151 | |
| 10152 | if (relation->rel_name == relName) |
| 10153 | { |
| 10154 | if (context) |
| 10155 | { |
| 10156 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-504) << |
| 10157 | Arg::Gds(isc_dsql_cursor_err) << |
| 10158 | Arg::Gds(isc_dsql_cursor_rel_ambiguous) << Arg::Str(relName) << |
| 10159 | cursor); |
| 10160 | } |
| 10161 | else |
| 10162 | context = candidate; |
| 10163 | } |
| 10164 | } |
| 10165 | //// TODO: LocalTableSourceNode |
| 10166 | else if (nodeIs<AggregateSourceNode>(recSource)) |
| 10167 | { |
| 10168 | // cursor with aggregation is not updatable |
| 10169 | ERRD_post(Arg::Gds(isc_sqlerr) << Arg::Num(-510) << |
| 10170 | Arg::Gds(isc_dsql_cursor_update_err) << cursor); |
| 10171 | } |
| 10172 | // note that UnionSourceNode and joins will cause the error below, |
| 10173 | // as well as derived tables. Some cases deserve fixing in the future |
| 10174 | } |
| 10175 | |
| 10176 | if (!context) |
no test coverage detected