| 99 | } |
| 100 | |
| 101 | bool NestedLoopJoin::internalGetRecord(thread_db* tdbb) const |
| 102 | { |
| 103 | JRD_reschedule(tdbb); |
| 104 | |
| 105 | Request* const request = tdbb->getRequest(); |
| 106 | Impure* const impure = request->getImpure<Impure>(m_impure); |
| 107 | |
| 108 | if (!(impure->irsb_flags & irsb_open)) |
| 109 | return false; |
| 110 | |
| 111 | if (m_joinType == INNER_JOIN) |
| 112 | { |
| 113 | if (impure->irsb_flags & irsb_first) |
| 114 | { |
| 115 | for (FB_SIZE_T i = 0; i < m_args.getCount(); i++) |
| 116 | { |
| 117 | m_args[i]->open(tdbb); |
| 118 | |
| 119 | if (!fetchRecord(tdbb, i)) |
| 120 | return false; |
| 121 | } |
| 122 | |
| 123 | impure->irsb_flags &= ~irsb_first; |
| 124 | } |
| 125 | // hvlad: self referenced members are removed from recursive SELECT's |
| 126 | // in recursive CTE (it is done in dsql\pass1.cpp). If there are no other |
| 127 | // members in such SELECT then rsb_count will be zero. Handle it. |
| 128 | else if (m_args.isEmpty()) |
| 129 | return false; |
| 130 | else if (!fetchRecord(tdbb, m_args.getCount() - 1)) |
| 131 | return false; |
| 132 | } |
| 133 | else if (m_joinType == SEMI_JOIN || m_joinType == ANTI_JOIN) |
| 134 | { |
| 135 | const auto outer = m_args[0]; |
| 136 | |
| 137 | if (impure->irsb_flags & irsb_first) |
| 138 | { |
| 139 | outer->open(tdbb); |
| 140 | |
| 141 | impure->irsb_flags &= ~irsb_first; |
| 142 | } |
| 143 | |
| 144 | while (true) |
| 145 | { |
| 146 | if (impure->irsb_flags & irsb_joined) |
| 147 | { |
| 148 | for (FB_SIZE_T i = 1; i < m_args.getCount(); i++) |
| 149 | m_args[i]->close(tdbb); |
| 150 | |
| 151 | impure->irsb_flags &= ~irsb_joined; |
| 152 | } |
| 153 | |
| 154 | if (!outer->getRecord(tdbb)) |
| 155 | return false; |
| 156 | |
| 157 | FB_SIZE_T stopArg = 0; |
| 158 |
nothing calls this directly
no test coverage detected