| 180 | } |
| 181 | |
| 182 | Sort* SortedStream::init(thread_db* tdbb) const |
| 183 | { |
| 184 | Request* const request = tdbb->getRequest(); |
| 185 | |
| 186 | m_next->open(tdbb); |
| 187 | |
| 188 | // Initialize for sort. If this is really a project operation, |
| 189 | // establish a callback routine to reject duplicate records. |
| 190 | |
| 191 | AutoPtr<Sort> scb(FB_NEW_POOL(request->req_sorts.getPool()) |
| 192 | Sort(tdbb->getDatabase(), &request->req_sorts, |
| 193 | m_map->length, m_map->keyItems.getCount(), m_map->keyItems.getCount(), |
| 194 | m_map->keyItems.begin(), |
| 195 | ((m_map->flags & FLAG_PROJECT) ? rejectDuplicate : nullptr), 0)); |
| 196 | |
| 197 | // Pump the input stream dry while pushing records into sort. For |
| 198 | // each record, map all fields into the sort record. The reverse |
| 199 | // mapping is done in get_sort(). |
| 200 | |
| 201 | dsc to, temp; |
| 202 | |
| 203 | while (m_next->getRecord(tdbb)) |
| 204 | { |
| 205 | // "Put" a record to sort. Actually, get the address of a place |
| 206 | // to build a record. |
| 207 | |
| 208 | UCHAR* data = nullptr; |
| 209 | scb->put(tdbb, reinterpret_cast<ULONG**>(&data)); |
| 210 | |
| 211 | // Zero out the sort key. This solves a multitude of problems. |
| 212 | |
| 213 | memset(data, 0, m_map->length); |
| 214 | |
| 215 | // Loop thru all field (keys and hangers on) involved in the sort. |
| 216 | // Be careful to null field all unused bytes in the sort key. |
| 217 | |
| 218 | const SortMap::Item* const end_item = m_map->items.begin() + m_map->items.getCount(); |
| 219 | for (const SortMap::Item* item = m_map->items.begin(); item < end_item; item++) |
| 220 | { |
| 221 | to = item->desc; |
| 222 | to.dsc_address = data + (IPTR) to.dsc_address; |
| 223 | bool flag = false; |
| 224 | dsc* from = nullptr; |
| 225 | |
| 226 | if (item->node) |
| 227 | { |
| 228 | from = EVL_expr(tdbb, request, item->node); |
| 229 | if (request->req_flags & req_null) |
| 230 | flag = true; |
| 231 | } |
| 232 | else |
| 233 | { |
| 234 | from = &temp; |
| 235 | |
| 236 | record_param* const rpb = &request->req_rpb[item->stream]; |
| 237 | |
| 238 | if (item->fieldId < 0) |
| 239 | { |
nothing calls this directly
no test coverage detected